该类继承自Writer类
引入了如下包:
import java.util.Objects; import java.util.Formatter; import java.util.Locale; import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException;
类头注释如下:
/** * Prints formatted representations of objects to a text-output stream. This * class implements all of the <tt>print</tt> methods found in {@link * PrintStream}. It does not contain methods for writing raw bytes, for which * a program should use unencoded byte streams. * * <p> Unlike the {@link PrintStream} class, if automatic flushing is enabled * it will be done only when one of the <tt>println</tt>, <tt>printf</tt>, or * <tt>format</tt> methods is invoked, rather than whenever a newline character * happens to be output. These methods use the platform's own notion of line * separator rather than the newline character. * * <p> Methods in this class never throw I/O exceptions, although some of its * constructors may. The client may inquire as to whether any errors have * occurred by invoking {@link #checkError checkError()}. * * @author Frank Yellin * @author Mark Reinhold * @since JDK1.1 */
大意如下:
向文本输出流打印对象的格式化表现形式
该类完成了全部的print方法(来自于PrintStream)
该类无写出原始byte数据的方法,对于这些字节,程序应选用为编码的字节流输出
不同于PrintStream类,如果自动自动刷新开启,程序将会在调用println,printf,format方法后自动刷新,而不是当新行符被输出时刷新
这些方法使用了各自操作系统规定的行分隔符概念而不是新行符
该类的方法永远不会抛出IO异常,尽管该类的一些构造函数会抛出
使用者需要查询是否有错误产生时需要调用checkError函数
该类含有如下的成员变量:
内含的字符输出流
protected Writer out;
自动刷新开启标识
private final boolean autoFlush;
是否产生错误标识
private boolean trouble = false;
格式转化器
private Formatter formatter;
内含的打印流
private PrintStream psOut = null;
系统行分隔符
private final String lineSeparator;
该类含有如下的成员方法:
返回输入字符串所代表的编码集
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); } }
构造函数(给予内嵌的字符输出流,默认不自动刷新
public PrintWriter (Writer out) { this(out, false); }
构造函数(给予内嵌字符输出流,给予刷新判断
public PrintWriter(Writer out, boolean autoFlush) { super(out);//绑定输出流 this.out = out; this.autoFlush = autoFlush; lineSeparator = java.security.AccessController.doPrivileged(//不检测权限 new sun.security.action.GetPropertyAction("line.separator"));//获得使用的行分隔符 }
构造函数(绑定字节输出流,默认不自动刷新
public PrintWriter(OutputStream out) { this(out, false); }
构造函数(绑定字节输出流,给予刷新判断
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) {//检测是否为PrintStream类 psOut = (PrintStream) out; } }
构造函数(给予输出文件路径
public PrintWriter(String fileName) throws FileNotFoundException { this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),//构造文件字符输出流 false); }
构造函数(给予使用的字符集,给予输出文件
private PrintWriter(Charset charset, File file) throws FileNotFoundException { this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)), false); }
构造函数(给予文件路径,给予字符集名称
public PrintWriter(String fileName, String csn) throws FileNotFoundException, UnsupportedEncodingException { this(toCharset(csn), new File(fileName)); }
构造函数(给予输出文件
public PrintWriter(File file) throws FileNotFoundException { this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))), false); }
构造函数(给予输出文件,给予字符集名称
public PrintWriter(File file, String csn) throws FileNotFoundException, UnsupportedEncodingException { this(toCharset(csn), file); }
确认流是否开启
private void ensureOpen() throws IOException { if (out == null) throw new IOException("Stream closed"); }
刷新该流
public void flush() { try { synchronized (lock) {//lock是Writer中声明的成员变量,保证对输出流的同步操作 ensureOpen(); out.flush(); } } catch (IOException x) { trouble = true; } }
关闭该流
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流 PrintWriter pw = (PrintWriter) out; return pw.checkError(); } else if (psOut != null) {//再检测是否有PrintStream return psOut.checkError(); } return trouble;//都不是或者都没有就抛出自身的 }
设置错误标志位
protected void setError() { trouble = true; }
清除错误标志位
protected void clearError() { trouble = false; }
写出单个字符(传入的是Ascii码
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; } }
写出整个字符数组
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; } }
写出整个字符串
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; } }
打印bool类型
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));//实际输入字符串 }
打印长整型
public void print(long l) { write(String.valueOf(l)); }
打印浮点型
public void print(float f) { write(String.valueOf(f)); }
打印双精度
public void print(double d) { write(String.valueOf(d)); }
打印字符数组
public void print(char s[]) { write(s); }
打印字符串
public void print(String s) { if (s == null) { s = "null"; } write(s); }
打印对象
public void print(Object obj) { write(String.valueOf(obj));//对象的字符串化,目前还没看过lang包,不是很清楚具体实现 }
打印换行符
public void println() { newLine(); }
打印bool加换行
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(); } }
打印长整型并换行
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(); } }打印字符串加换行
public void println(String x) { synchronized (lock) { print(x); println(); } }
打印对象加换行
public void println(Object x) { String s = String.valueOf(x); synchronized (lock) { print(s); println(); } }
打印特定格式的对象数据
public PrintWriter printf(String format, Object ... args) { return format(format, args); }
打印根据特定地方和特定格式的对象数据
public PrintWriter printf(Locale l, String format, Object ... args) { return format(l, format, 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; }
构建格式转化器(使用给定的地理信息
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; }
向缓冲区中添加字符序列(主要是为了返回当前对象
public PrintWriter append(CharSequence csq) { if (csq == null) write("null"); else write(csq.toString()); return this; }
向缓冲区中添加字符序列(特定区间
public PrintWriter append(CharSequence csq, int start, int end) { CharSequence cs = (csq == null ? "null" : csq); write(cs.subSequence(start, end).toString()); return this; }
向缓冲区中添加字符
public PrintWriter append(char c) { write(c); return this; }
对于该类,你可以理解为是PrintStream的字符流形式。除了需要注意autoFlush的刷新机制不同以外(刷新判断位置在格式输出和创建新行下,与PrintStream不太一样,因此效果也有所不同),该类并不对字节流服务,使用字节流就请使用PrintStream