今天来学习PrintWriter。
PrintWriter,字符类型的打印输出流,用于控制文本输出流打印对象的格式化表示形式。此类实现在PrintStream中的所有print方法。它不包含用于写入原始字节的方法。
此类中的方法不会抛出I/O异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用checkError()是否出现错误。
ps:如果不想看源码,文章末尾有对源码的总结。
源码
下面看下PrintWriter的源码。
public class PrintWriter extends Writer {
/**
* PrintWriter的底层字符输出流
*/
protected Writer out;
//是否自动刷新。
//如果为true,每次执行print(), println(), write()函数,都会调用flush()函数。
private final boolean autoFlush;
//是否有异常
//当PrintWriter有异常产生时,会被本身捕获,并设置trouble为true
private boolean trouble = false;
//用于格式化字符串的对象
private Formatter formatter;
//字节打印流
//用于checkError方法
private PrintStream psOut = null;
/**
* 行分隔符
* 在PrintWriter被创建时line.separator属性的值。
*/
private final String lineSeparator;
/**
* 返回csn(字符集名字)对应的Chaset
* csn为null或是不支持的字符集,抛出异常
*/
private static Charset toCharset(String csn)
throws UnsupportedEncodingException
{
Objects.requireNonNull(csn, "charsetName");
try {
return Charset.forName(csn);
} catch (IllegalCharsetNameException|UnsupportedCharsetException unused) {
// UnsupportedEncodingException should be thrown
throw new UnsupportedEncodingException(csn);
}
}
/**
* 创建新的PrintWriter。
* 指定底层输出流,默认不会自动flush,采用默认字符集
*/
public PrintWriter (Writer out) {
this(out, false);
}
/**
* 创建新的PrintWriter。
* 指定底层输出流,指定是否自动flush,采用默认字符集
*/
public PrintWriter(Writer out,
boolean autoFlush) {
super(out);
this.out = out;
this.autoFlush = autoFlush;
//line.separator属性的值
lineSeparator = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("line.separator"));
}
/**
* 创建新的PrintWriter。
* 指定底层输出流,不自动flush,采用默认字符集
*/
public PrintWriter(OutputStream out) {
this(out, false);
}
/**
* 创建新的PrintWriter。
* 指定底层输出流,指定是否自动flush,采用默认字符集
*/
public PrintWriter(OutputStream out, boolean autoFlush) {
this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush);
// save print stream for error propagation
if (out instanceof java.io.PrintStream) {
psOut = (PrintStream) out;
}
}
/**
* 创建新的PrintWriter。
* 指定文件名,默认不自动flush,采用默认字符集
*/
public PrintWriter(String fileName) throws FileNotFoundException {
this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
false);
}
/**
* 私有构造方法。创建新的PrintWriter。
* 指定文件名,默认不自动flush,采用指定字符集
*/
private PrintWriter(Charset charset, File file)
throws FileNotFoundException
{
this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)),
false);
}
/**
* 创建新的PrintWriter。
* 指定文件名,默认不自动flush,采用指定字符集
*/
public PrintWriter(String fileName, String csn)
throws FileNotFoundException, UnsupportedEncodingException
{
this(toCharset(csn), new File(fileName));
}
/**
* 创建新的PrintWriter。
* 指定文件名,默认不自动flush,采用默认字符集
*/
public PrintWriter(File file) throws FileNotFoundException {
this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
false);
}
/**
* 创建新的PrintWriter。
* 指定文件名,默认不自动flush,采用指定字符集
*/
public PrintWriter(File file, String csn)
throws FileNotFoundException, UnsupportedEncodingException
{
this(toCharset(csn), file);
}
/** 确认输出流是否开启。如果底层输出流不为null,则认为输出流是开启的 */
private void ensureOpen() throws IOException {
if (out == null)
throw new IOException("Stream closed");
}
/**
* 刷新流
* @see #checkError()
*/
public void flush() {
try {
synchronized (lock) {
ensureOpen();
out.flush();
}
}
catch (IOException x) {
//当PrintWriter有异常产生时,会被本身捕获,并设置trouble为true
trouble = true;
}
}
/**
* 关闭该流并释放与之关联的所有系统资源。
* 将底层输出流置为null,就把输出流关闭了
*
* @see #checkError()
*/
public void close() {
try {
synchronized (lock) {
if (out == null)
return;
out.close();
out = null;
}
}
catch (IOException x) {
trouble = true;
}
}
/**
* 如果流没有关闭,则刷新流且检查其错误状态。
*/
public boolean checkError() {
//如果流没有关闭,则刷新流
if (out != null) {
flush();
}
//检查错误状态
if (out instanceof java.io.PrintWriter) {
PrintWriter pw = (PrintWriter) out;
return pw.checkError();
} else if (psOut != null) {
return psOut.checkError();
}
//如果抛出了异常,返回true
return trouble;
}
/**
* 指示已发生错误。
* 在调用clearError()之前,此方法将导致checkError()的后续调用返回 true。
*/
protected void setError() {
trouble = true;
}
/**
* 清除此流的错误状态。
*/
protected void clearError() {
trouble = false;
}
/**
* 写入单个字符。
*/
public void write(int c) {
try {
synchronized (lock) {
ensureOpen();
//调用底层输出流写入单个字符
out.write(c);
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
/**
* 写入字符数组的某一部分。
*/
public void write(char buf[], int off, int len) {
try {
synchronized (lock) {
ensureOpen();
//调用底层输出流写入字符数组的某一部分
out.write(buf, off, len);
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
/**
* 写入字符数组。
* 此方法不能从Writer类继承,因为它必须取消I/O异常。
*/
public void write(char buf[]) {
write(buf, 0, buf.length);
}
/**
* 写入字符串的某一部分。
*/
public void write(String s, int off, int len) {
try {
synchronized (lock) {
ensureOpen();
out.write(s, off, len);
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
/**
* 写入字符串。
* 此方法不能从Writer类继承,因为它必须取消I/O异常。
*/
public void write(String s) {
write(s, 0, s.length());
}
//写入换行符
private void newLine() {
try {
synchronized (lock) {
ensureOpen();
out.write(lineSeparator);
if (autoFlush)
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
/* Methods that do not terminate lines */
/**
* 打印boolean值。
* 按照平台的默认字符编码将字符串转换为字节,然后写入输出流。
*/
public void print(boolean b) {
write(b ? "true" : "false");
}
/**
* 打印字符。
*/
public void print(char c) {
write(c);
}
/**
* 打印整数。
* 按照平台的默认字符编码将字符串转换为字节,然后写入输出流。
*/
public void print(int i) {
write(String.valueOf(i));
}
/**
* 打印long。
* 按照平台的默认字符编码将字符串转换为字节,然后写入输出流。
*/
public void print(long l) {
write(String.valueOf(l));
}
/**
* 打印一个浮点数。
* 按照平台的默认字符编码将字符串转换为字节,然后写入输出流。
*/
public void print(float f) {
write(String.valueOf(f));
}
/**
* 打印double精度浮点数。
* 按照平台的默认字符编码将字符串转换为字节,然后写入输出流。
*/
public void print(double d) {
write(String.valueOf(d));
}
/**
* 打印字符数组。
* 按照平台的默认字符编码将字符转换为字节,然后写入输出流。
*/
public void print(char s[]) {
write(s);
}
/**
* 打印字符串。
* 如果参数为null,则打印字符串"null"
* 否则,按照平台的默认字符编码将字符串的字符转换为字节,然后写入输出流。
*/
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
/**
* 打印对象。
* 按照平台的默认字符串编码将String.valueOf(Object)方法生成的字符串转换为字节,
* 并完全以 write(int) 方法的方式写入这些字节。
*/
public void print(Object obj) {
write(String.valueOf(obj));
}
/* Methods that do terminate lines */
/**
* 通过写入行分隔符字符串终止当前行。
* 行分隔符字符串由系统属性line.separator定义,不一定是单个换行符('\n')。
*/
public void println() {
newLine();
}
/**
* 打印boolean值,然后终止该行。
*/
public void println(boolean x) {
synchronized (lock) {
print(x);
println();
}
}
/**
* 打印字符,然后终止该行。
*/
public void println(char x) {
synchronized (lock) {
print(x);
println();
}
}
/**
* 打印整数,然后终止该行。
*/
public void println(int x) {
synchronized (lock) {
print(x);
println();
}
}
/**
* 打印long整数,然后终止该行。
*/
public void println(long x) {
synchronized (lock) {
print(x);
println();
}
}
/**
* 打印浮点数,然后终止该行。
*/
public void println(float x) {
synchronized (lock) {
print(x);
println();
}
}
/**
* 打印双精度浮点数,然后终止该行。
*/
public void println(double x) {
synchronized (lock) {
print(x);
println();
}
}
/**
* 打印字符数组,然后终止该行。
*/
public void println(char x[]) {
synchronized (lock) {
print(x);
println();
}
}
/**
* 打印String,然后终止该行。
*/
public void println(String x) {
synchronized (lock) {
print(x);
println();
}
}
/**
* 打印Object,然后终止该行。
*/
public void println(Object x) {
String s = String.valueOf(x);
synchronized (lock) {
print(s);
println();
}
}
/**
* 使用指定格式字符串和参数将一个格式化字符串写入此writer中。
* 如果启用自动刷新,则调用此方法将刷新输出缓冲区。
*
* @param format 在格式字符串的语法中描述的格式字符串。
* 格式字符串的语法可以参考http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/Formatter.html#syntax
*
* @param args
* 格式字符串中的格式说明符引用的参数。如果参数多于格式说明符,则忽略额外的参数。参数的数量是可变的,并且可以为零。
*
* @since 1.5
*/
public PrintWriter printf(String format, Object ... args) {
return format(format, args);
}
/**
* 使用指定格式字符串和参数将一个格式化字符串写入此writer中。
* 如果启用自动刷新,则调用此方法将刷新输出缓冲区。
*
* @param l
* 格式化过程中应用的locale。如果l为null,则不应用本地化。
*
* @param format
* 在格式字符串的语法中描述的格式字符串。
*
* @param args
* 格式字符串中的格式说明符引用的参数。
*
* @since 1.5
*/
public PrintWriter printf(Locale l, String format, Object ... args) {
return format(l, format, args);
}
/**
* 参考public PrintWriter printf(String format, Object... args)
*/
public PrintWriter format(String format, Object ... args) {
try {
synchronized (lock) {
ensureOpen();
if ((formatter == null)
|| (formatter.locale() != Locale.getDefault()))
formatter = new Formatter(this);
formatter.format(Locale.getDefault(), format, args);
if (autoFlush)
out.flush();
}
} catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
} catch (IOException x) {
trouble = true;
}
return this;
}
/**
* 参考printf(Locale l, String format, Object... args)
*/
public PrintWriter format(Locale l, String format, Object ... args) {
try {
synchronized (lock) {
ensureOpen();
if ((formatter == null) || (formatter.locale() != l))
formatter = new Formatter(this, l);
formatter.format(l, format, args);
if (autoFlush)
out.flush();
}
} catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
} catch (IOException x) {
trouble = true;
}
return this;
}
/**
* 将指定的字符序列添加到此writer。
* 可能不添加整个序列,也可能添加,具体取决于字符序列csq的toString指定。
*
* @since 1.5
*/
public PrintWriter append(CharSequence csq) {
if (csq == null)
write("null");
else
write(csq.toString());
return this;
}
/**
* 将指定字符序列的子序列添加到此writer。
*
* @since 1.5
*/
public PrintWriter append(CharSequence csq, int start, int end) {
CharSequence cs = (csq == null ? "null" : csq);
write(cs.subSequence(start, end).toString());
return this;
}
/**
* 将指定字符添加到此 writer。
*
* @since 1.5
*/
public PrintWriter append(char c) {
write(c);
return this;
}
}
总结
- 从构造方法中可以看到,BufferedWriter包装了底层输出流,为其提供了缓冲功能。
- 此类中的方法不会抛出I/O异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用checkError()是否出现错误。
- print方法可以打印boolean、char 、char[]、double 、float、int、 long、Object、String这些类型。都是按照平台的默认字符串编码将String.valueOf() 方法生成的字符串转换为字节,并完全以write(int)方法的方式向输出流中写入这些字节。
- println(type param)方法可以打印boolean、char 、char[]、double 、float、int、 long、Object、String这些类型。都是先调用print方法打印,再调用println()方法换行。
- printf方法和format方法的效果是相同的。因为printf方法是依赖于调用format方法实现的。
- append方法其实是依赖于out.write方法实现的。
关于PrintWriter就讲到这里,想了解更多内容请参考
版权声明 |
---|
作者:潘威威 原文地址:CSDN博客-潘威威的博客-http://blog.csdn.net/panweiwei1994/article/details/78389254 本文版权归作者所有,欢迎转载。转载时请在文章明显位置给出原文作者名字(潘威威)及原文链接。请勿将本文用于任何商业用途。 |