Java
Java IO

Java IO 26 - PrintWriter详解

简介:流是一组有顺序的,有起点和终点的字节集合。是对设备文件间数据传输的总称和抽象。

1. PrintWriter介绍

PrintWriter是字符类型的打印输出流,继承于Writer。PrintStream用于向文本输出流打印对象的格式化表示形式,它实现在PrintStream中的所有print方法。它不包含用于写入原始字节的方法,对于这些字节,程序应该使用未编码的字节流进行写入。

2. PrintWriter函数列表

  • PrintWriter(OutputStream out)
  • PrintWriter(OutputStream out, boolean autoFlush)
  • PrintWriter(Writer wr)
  • PrintWriter(Writer wr, boolean autoFlush)
  • PrintWriter(File file)
  • PrintWriter(File file, String csn)
  • PrintWriter(String fileName)
  • PrintWriter(String fileName, String csn)
  • PrintWriter append(char c)
  • PrintWriter append(CharSequence csq, int start, int end)
  • PrintWriter append(CharSequence csq)
  • boolean checkError()
  • void close()
  • void flush()
  • PrintWriter format(Locale l, String format, Object... args)
  • PrintWriter format(String format, Object... args)
  • void print(float fnum)
  • void print(double dnum)
  • void print(String str)
  • void print(Object obj)
  • void print(char ch)
  • void print(char[] charArray)
  • void print(long lnum)
  • void print(int inum)
  • void print(boolean bool)
  • PrintWriter printf(Locale l, String format, Object... args)
  • PrintWriter printf(String format, Object... args)
  • void println()
  • void println(float f)
  • void println(int i)
  • void println(long l)
  • void println(Object obj)
  • void println(char[] chars)
  • void println(String str)
  • void println(char c)
  • void println(double d)
  • void println(boolean b)
  • void write(char[] buf, int offset, int count)
  • void write(int oneChar)
  • void write(char[] buf)
  • void write(String str, int offset, int count)
  • void write(String str)

3. PrintWriter源码分析

下面是PrintWriter的源码,基于JDK 1.7.0_07:

  • package java.io;
  • 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;
  • public class PrintWriter extends Writer {
  • protected Writer out;
  • // 自动flush
  • // 所谓自动flush,就是每次执行print()、println()、write()函数,都会调用flush()函数
  • // 而不自动flush,则需要我们手动调用flush()接口
  • private final boolean autoFlush;
  • // PrintWriter是否右产生异常,当PrintWriter有异常产生时,会被本身捕获,并设置trouble为true
  • private boolean trouble = false;
  • // 用于格式化的对象
  • private Formatter formatter;
  • private PrintStream psOut = null;
  • // 行分割符
  • private final String lineSeparator;
  • // 获取csn(字符集名字)对应的Chaset
  • 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);
  • }
  • }
  • // 将Writer对象out作为PrintWriter的输出流,默认不会自动flush,并且采用默认字符集
  • public PrintWriter (Writer out) {
  • this(out, false);
  • }
  • // 将Writer对象out作为PrintWriter的输出流,autoFlush的flush模式,并且采用默认字符集
  • 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"));
  • }
  • // 将输出流对象out作为PrintWriter的输出流,不自动flush,并且采用默认字符集
  • public PrintWriter(OutputStream out) {
  • this(out, false);
  • }
  • // 将输出流对象out作为PrintWriter的输出流,autoFlush的flush模式,并且采用默认字符集
  • public PrintWriter(OutputStream out, boolean autoFlush) {
  • // new OutputStreamWriter(out):将字节类型的输出流转换为字符类型的输出流
  • // new BufferedWriter(...): 为输出流提供缓冲功能
  • this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush);
  • // save print stream for error propagation
  • if (out instanceof java.io.PrintStream) {
  • psOut = (PrintStream) out;
  • }
  • }
  • // 创建fileName对应的OutputStreamWriter,进而创建BufferedWriter对象;然后将该BufferedWriter作为PrintWriter的输出流,不自动flush,采用默认字符集
  • public PrintWriter(String fileName) throws FileNotFoundException {
  • this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
  • false);
  • }
  • // 创建fileName对应的OutputStreamWriter,进而创建BufferedWriter对象;然后将该BufferedWriter作为PrintWriter的输出流,不自动flush,采用字符集charset
  • private PrintWriter(Charset charset, File file)
  • throws FileNotFoundException
  • {
  • this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)),
  • false);
  • }
  • // 创建fileName对应的OutputStreamWriter,进而创建BufferedWriter对象;然后将该BufferedWriter作为PrintWriter的输出流,不自动flush,采用csn字符集
  • public PrintWriter(String fileName, String csn)
  • throws FileNotFoundException, UnsupportedEncodingException
  • {
  • this(toCharset(csn), new File(fileName));
  • }
  • // 创建file对应的OutputStreamWriter,进而创建BufferedWriter对象;然后将该BufferedWriter作为PrintWriter的输出流,不自动flush,采用默认字符集
  • public PrintWriter(File file) throws FileNotFoundException {
  • this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
  • false);
  • }
  • // 创建file对应的OutputStreamWriter,进而创建BufferedWriter对象;然后将该BufferedWriter作为PrintWriter的输出流,不自动flush,采用csn字符集
  • 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");
  • }
  • // flushPrintWriter输出流中的数据
  • public void flush() {
  • try {
  • synchronized (lock) {
  • 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;
  • }
  • }
  • // flushPrintWriter输出流缓冲中的数据,并检查错误
  • 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();
  • }
  • return trouble;
  • }
  • protected void setError() {
  • trouble = true;
  • }
  • protected void clearError() {
  • trouble = false;
  • }
  • // 将字符c写入到PrintWriter输出流中,c虽然是int类型,但实际只会写入一个字符
  • public void write(int c) {
  • try {
  • synchronized (lock) {
  • ensureOpen();
  • out.write(c);
  • }
  • }
  • catch (InterruptedIOException x) {
  • Thread.currentThread().interrupt();
  • }
  • catch (IOException x) {
  • trouble = true;
  • }
  • }
  • // 将buf中从off开始的len个字符写入到PrintWriter输出流中
  • 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;
  • }
  • }
  • // 将buf中的全部数据写入到PrintWriter输出流中
  • public void write(char buf[]) {
  • write(buf, 0, buf.length);
  • }
  • // 将字符串s中从off开始的len个字符写入到PrintWriter输出流中
  • 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;
  • }
  • }
  • // 将字符串s写入到PrintWriter输出流中
  • public void write(String s) {
  • write(s, 0, s.length());
  • }
  • // 将换行符写入到PrintWriter输出流中
  • 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;
  • }
  • }
  • // 将boolean数据对应的字符串写入到PrintWriter输出流中,print实际调用的是write函数
  • public void print(boolean b) {
  • write(b ? "true" : "false");
  • }
  • // 将字符c对应的字符串写入到PrintWriter输出流中,print实际调用的是write函数
  • public void print(char c) {
  • write(c);
  • }
  • // 将int数据i对应的字符串写入到PrintWriter输出流中,print实际调用的是write函数
  • public void print(int i) {
  • write(String.valueOf(i));
  • }
  • // 将long型数据l对应的字符串写入到PrintWriter输出流中,print实际调用的是write函数
  • public void print(long l) {
  • write(String.valueOf(l));
  • }
  • // 将float数据f对应的字符串写入到PrintWriter输出流中,print实际调用的是write函数
  • public void print(float f) {
  • write(String.valueOf(f));
  • }
  • // 将double数据d对应的字符串写入到PrintWriter输出流中,print实际调用的是write函数
  • public void print(double d) {
  • write(String.valueOf(d));
  • }
  • // 将字符数组s写入到PrintWriter输出流中,print实际调用的是write函数
  • public void print(char s[]) {
  • write(s);
  • }
  • // 将字符串数据s写入到PrintWriter输出流中,print实际调用的是write函数
  • public void print(String s) {
  • if (s == null) {
  • s = "null";
  • }
  • write(s);
  • }
  • // 将对象obj对应的字符串写入到PrintWriter输出流中,print实际调用的是write函数
  • public void print(Object obj) {
  • write(String.valueOf(obj));
  • }
  • // 将换行符写入到PrintWriter输出流中,println实际调用的是write函数
  • public void println() {
  • newLine();
  • }
  • // 将boolean数据对应的字符串+换行符写入到PrintWriter输出流中,println实际调用的是write函数
  • public void println(boolean x) {
  • synchronized (lock) {
  • print(x);
  • println();
  • }
  • }
  • // 将字符x对应的字符串+换行符写入到PrintWriter输出流中,println实际调用的是write函数
  • public void println(char x) {
  • synchronized (lock) {
  • print(x);
  • println();
  • }
  • }
  • // 将int数据对应的字符串+换行符写入到PrintWriter输出流中,println实际调用的是write函数
  • public void println(int x) {
  • synchronized (lock) {
  • print(x);
  • println();
  • }
  • }
  • // 将long数据对应的字符串+换行符写入到PrintWriter输出流中,println实际调用的是write函数
  • public void println(long x) {
  • synchronized (lock) {
  • print(x);
  • println();
  • }
  • }
  • // 将float数据对应的字符串+换行符写入到PrintWriter输出流中,println实际调用的是write函数
  • public void println(float x) {
  • synchronized (lock) {
  • print(x);
  • println();
  • }
  • }
  • // 将double数据对应的字符串+换行符写入到PrintWriter输出流中,println实际调用的是write函数
  • public void println(double x) {
  • synchronized (lock) {
  • print(x);
  • println();
  • }
  • }
  • // 将字符数组x+换行符写入到PrintWriter输出流中,println实际调用的是write函数
  • public void println(char x[]) {
  • synchronized (lock) {
  • print(x);
  • println();
  • }
  • }
  • // 将字符串x+换行符写入到PrintWriter输出流中,println实际调用的是write函数
  • public void println(String x) {
  • synchronized (lock) {
  • print(x);
  • println();
  • }
  • }
  • // 将对象o对应的字符串+换行符写入到PrintWriter输出流中,println实际调用的是write函数
  • public void println(Object x) {
  • String s = String.valueOf(x);
  • synchronized (lock) {
  • print(s);
  • println();
  • }
  • }
  • // 将数据args根据默认Locale值(区域属性)按照format格式化,并写入到PrintWriter输出流中
  • public PrintWriter printf(String format, Object ... args) {
  • return format(format, args);
  • }
  • // 将数据args根据Locale值(区域属性)按照format格式化,并写入到PrintWriter输出流中
  • public PrintWriter printf(Locale l, String format, Object ... args) {
  • return format(l, format, args);
  • }
  • // 根据默认的Locale值(区域属性)来格式化数据
  • 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;
  • }
  • // 根据Locale值(区域属性)来格式化数据
  • 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;
  • }
  • // 将字符序列的全部字符追加到PrintWriter输出流中
  • public PrintWriter append(CharSequence csq) {
  • if (csq == null)
  • write("null");
  • else
  • write(csq.toString());
  • return this;
  • }
  • // 将字符序列从start(包括)到end(不包括)的全部字符追加到PrintWriter输出流中
  • public PrintWriter append(CharSequence csq, int start, int end) {
  • CharSequence cs = (csq == null ? "null" : csq);
  • write(cs.subSequence(start, end).toString());
  • return this;
  • }
  • // 将字符c追加到PrintWriter输出流中
  • public PrintWriter append(char c) {
  • write(c);
  • return this;
  • }
  • }

4. PrintWriter示例

  • package com.coderap;
  • import java.io.FileOutputStream;
  • import java.io.FileWriter;
  • import java.io.IOException;
  • import java.io.PrintWriter;
  • import java.util.Date;
  • public class PrintWriterTest {
  • public static void main(String[] args) throws IOException {
  • PrintWriter printWriter = new PrintWriter("file.data");
  • for (int i = 0; i < 26; i++) {
  • printWriter.write('a' + i);
  • }
  • printWriter.print('\n');
  • printWriter.close();
  • PrintWriter printWriter1 = new PrintWriter(new FileWriter("file.data", true));
  • for (int i = 0; i < 26; i++) {
  • printWriter1.write('A' + i);
  • }
  • printWriter1.print('\n');
  • printWriter1.close();
  • PrintWriter printWriter2 = new PrintWriter(new FileOutputStream("file.data", true));
  • for (int i = 0; i < 10; i++) {
  • printWriter2.write('0' + i);
  • }
  • printWriter2.print('\n');
  • printWriter2.append('!');
  • printWriter2.append('@');
  • printWriter2.append('#');
  • printWriter2.append('$');
  • printWriter2.print('\n');
  • printWriter2.print(0x41);
  • printWriter2.print(", ");
  • printWriter2.print(0x42);
  • printWriter2.print(", ");
  • printWriter2.print(0x43);
  • printWriter2.print('\n');
  • String tipStr = "Current Timestamp";
  • long timestamp = new Date().getTime();
  • printWriter2.printf("%s is %d\n", tipStr, timestamp);
  • printWriter2.close();
  • }
  • }

运行上述代码会创建一个file.data文件,内容如下:

  • abcdefghijklmnopqrstuvwxyz
  • ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • 0123456789
  • !@#$
  • 65, 66, 67
  • Current Timestamp is 1537255356692