Java PrintWriter类

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

构造函数

PrintWriter(File file)       使用指定文件创建不具有自动行刷新的新 PrintWriter。   
PrintWriter(File file, String csn)       创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。   
PrintWriter(OutputStream out     根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。   
PrintWriter(OutputStream out, boolean autoFlush)     通过现有的 OutputStream 创建新的 PrintWriter。   
PrintWriter(String fileName)    创建具有指定文件名称且不带自动行刷新的新 PrintWriter。   
PrintWriter(String fileName, String csn)    创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。   
PrintWriter(Writer out)     创建不带自动行刷新的新 PrintWriter。   
PrintWriter(Writer out, boolean autoFlush)      创建新 PrintWriter。   

关键字

protected Writer out;   传入的底层字符输出流  
private boolean autoFlush = false;      是否自动刷新  
private boolean trouble = false;    是否抛异常     
private Formatter formatter;    格式化类  
private PrintStream psOut = null;       字节打印流、用于checkError方法  

方法

PrintWriter append(char c)    将指定字符添加到此 writer。   
PrintWriter append(CharSequence csq)     将指定的字符序列添加到此 writer。   
PrintWriter append(CharSequence csq, int start, int end)     将指定字符序列的子序列添加到此 writer。   
boolean checkError()     如果流没有关闭,则刷新流且检查其错误状态。   
protected  void clearError()     清除此流的错误状态。   
void close()     关闭该流并释放与之关联的所有系统资源。   
void flush()     刷新该流的缓冲。   
PrintWriter format(Locale l, String format, Object... args)      使用指定格式字符串和参数将一个格式化字符串写入此 writer 中。   
PrintWriter format(String format, Object... args)        使用指定格式字符串和参数将一个格式化字符串写入此 writer 中。   
void print(boolean b)         打印 boolean 值。   
void print(char c)        打印字符。   
void print(char[] s)      打印字符数组。   
void print(double d)      打印 double 精度浮点数。   
void print(float f)      打印一个浮点数。   
void print(int i)         打印整数。   
void print(long l)       打印 long 整数。   
void print(Object obj)       打印对象。   
void print(String s)     打印字符串。   
PrintWriter printf(Locale l, String format, Object... args)      使用指定格式字符串和参数将格式化的字符串写入此 writer 的便捷方法。   
PrintWriter printf(String format, Object... args)        使用指定格式字符串和参数将格式化的字符串写入此 writer 的便捷方法。   
void println()       通过写入行分隔符字符串终止当前行。   
void println(boolean x)       打印 boolean 值,然后终止该行。   
void println(char x)      打印字符,然后终止该行。   
void println(char[] x)       打印字符数组,然后终止该行。   
void println(double x)        打印双精度浮点数,然后终止该行。   
void println(float x)        打印浮点数,然后终止该行。   
void println(int x)       打印整数,然后终止该行。   
void println(long x)      打印 long 整数,然后终止该行。   
void println(Object x)       打印 Object,然后终止该行。   
void println(String x)       打印 String,然后终止该行。   
protected  void setError()       指示已发生错误。   
void write(char[] buf)        写入字符数组。   
void write(char[] buf, int off, int len)      写入字符数组的某一部分。   
void write(int c)         写入单个字符。   
void write(String s)     写入字符串。   
void write(String s, int off, int len)       写入字符串的某一部分。  

源码分析

public class PrintWriter extends Writer {  
    /** 
     * 被PrintWriter装饰的底层Writer、OutputStream实现类out 
     */  
    protected Writer out;  
    //是否自动刷新  
    private boolean autoFlush = false;  
    //是否抛异常  
    private boolean trouble = false;  
    //格式化类  
    private Formatter formatter;  
    //字节打印流、用于checkError方法  
    private PrintStream psOut = null;  
    /** 
     * 换行符 
     */  
    private String lineSeparator;  
    /** 
     * 根据传入的Writer实现类out创建PrintWriter、不具有自动flush功能。 
     */  
    public PrintWriter (Writer out) {  
        this(out, false);  
    }  
  
    /** 
     * 创建PrintWriter、指定autoFlush、并且根据平台不同初始化linSeparator 
     */  
    public PrintWriter(Writer out,  
               boolean autoFlush) {  
        super(out);  
        this.out = out;  
        this.autoFlush = autoFlush;  
        lineSeparator = (String) java.security.AccessController.doPrivileged(  
                   new sun.security.action.GetPropertyAction("line.separator"));  
    }  
  
    /** 
     * 根据OutputStream out创建PrintWriter。不具有自动flush功能。 
     */  
    public PrintWriter(OutputStream out) {  
        this(out, false);  
    }  
  
    /** 
     * 根据底层OutputStream out创建pw、指定是否具有autoFlush功能。 
     * 本质只是将out转换成writer、然后为其添加缓冲功能、再用PrintWriter装饰一下。 
     * 如果传入的是PrintStream、则赋给全局变量psOut 
     */  
    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 = (java.io.PrintStream) out;  
        }  
    }  
  
    /** 
     * 根据传入的文件名构造不具有自动flush功能的PrintWriter。 
     * 本质还是根据文件名创建文件字节输出流out、再将out转换成writer、对其添加缓冲功能、最后用pw装饰。 
     */  
    public PrintWriter(String fileName) throws FileNotFoundException {  
        this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),  
             false);  
    }  
  
    /** 
     * 与上面一样、只是多了一个可以使用指定编码读取的功能。 
     */  
    public PrintWriter(String fileName, String csn)  
        throws FileNotFoundException, UnsupportedEncodingException  
        {  
        this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)),  
             false);  
    }  
  
    /** 
     * 根据传入的文件构造不具有自动flush功能的PrintWriter。 
     * 本质还是根据文件名创建文件字节输出流out、再将out转换成writer、对其添加缓冲功能、最后用pw装饰。 
     */  
    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(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)),  
             false);  
    }  
  
    /** 检测底层流是否关闭 */  
    private void ensureOpen() throws IOException {  
        if (out == null)  
            throw new IOException("Stream closed");  
    }  
  
    /** 
     * flush底层流 
     */  
    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;  
        }  
    }  
  
    /** 
     * 同PrintStream一样、不会抛出IO异常、出现异常时只会自己内部消化掉、 
     * 可以通过此方法来查看print过程中是否有异常出现。 
     */  
    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;  
    }  
  
    /** 
     * 可以显示的设置print产生异常。 
     */  
    protected void setError() {  
        trouble = true;  
    }  
  
    /** 
     * 清除异常信息 
     */  
    protected void clearError() {  
        trouble = false;  
    }  
   
  
    /** 
     * 写入一个字符、 
     * 这里产生IOException的原因是此方法是继承自Writer 
     */  
    public void write(int c) {  
        try {  
            synchronized (lock) {  
            ensureOpen();  
            out.write(c);  
            }  
        }  
        catch (InterruptedIOException x) {  
            Thread.currentThread().interrupt();  
        }  
        catch (IOException x) {  
            trouble = true;  
        }  
    }  
  
    /** 
     * 将从下标off开始、len个字符写入到out中。 
     * 这里也许会有个疑问?当传入的out是OutputStream时还能使用 
     * out.write(char[] buf, int off, int len)吗? 
     * 可以:当传入OutputStream时、调用的构造方法内部会将OutputStream 
     * 包装成OutputStreamWriter、同时使用BufferedWriter来封装、最后再用PrintWriter来装饰。 
     * 这里的out表示的已经变成BufferedWriter。 
     */  
    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;  
        }  
    }  
  
    /** 
     * 将一个字符数组中所有字符写入到out中 
     */  
    public void write(char buf[]) {  
        write(buf, 0, buf.length);  
    }  
  
    /** 
     * 将s的一部分写入out中 
     */  
    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;  
        }  
    }  
  
    /** 
     * 将String写入out中 
     */  
    public void write(String s) {  
        write(s, 0, s.length());  
    }  
  
    /** 
     * 将一个换行符写入out中、如果设置了自动刷新、则刷新out。 
     */  
    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写入out中、不管有没有设置autoFlush、都不会自动flush 
     */  
    public void print(boolean b) {  
        write(b ? "true" : "false");  
    }  
  
    /** 
     * 将一个char写入out中、  
     */  
    public void print(char c) {  
        write(c);  
    }  
  
    /** 
     * 将一个int写入out中、  
     */  
    public void print(int i) {  
        write(String.valueOf(i));  
    }  
  
    /** 
     * 将一个long写入out中、  
     */  
    public void print(long l) {  
        write(String.valueOf(l));  
    }  
  
    /** 
     * 将一个float写入out中、 rinted 
     */  
    public void print(float f) {  
        write(String.valueOf(f));  
    }  
  
    /** 
     * 将一个double写入out中、  
     */  
    public void print(double d) {  
        write(String.valueOf(d));  
    }  
  
    /** 
     *将一个char[]写入out中、  
     */  
    public void print(char s[]) {  
        write(s);  
    }  
  
    /** 
     * 将一个String写入out中、  
     */  
    public void print(String s) {  
        if (s == null) {  
            s = "null";  
        }  
        write(s);  
    }  
  
    /** 
     * 将一个Object写入out中、  
     */  
    public void print(Object obj) {  
        write(String.valueOf(obj));  
    }  
  
    /* Methods that do terminate lines */  
  
    /** 
     * 将一个换行符写入out中、  
     */  
    public void println() {  
        newLine();  
    }  
  
    /** 
     * 将一个换行符写入out中、  
     */  
    public void println(boolean x) {  
        synchronized (lock) {  
            print(x);  
            println();  
        }  
    }  
  
    /** 
     * 将一个换行符写入out中、  
     */  
    public void println(char x) {  
        synchronized (lock) {  
            print(x);  
            println();  
        }  
    }  
  
    /** 
     * 将一个换行符写入out中、  
     */  
    public void println(int x) {  
        synchronized (lock) {  
            print(x);  
            println();  
        }  
    }  
  
    /** 
     * 将一个换行符写入out中、  
     */  
    public void println(long x) {  
        synchronized (lock) {  
            print(x);  
            println();  
        }  
    }  
  
    /** 
     * 将一个换行符写入out中、  
     */  
    public void println(float x) {  
        synchronized (lock) {  
            print(x);  
            println();  
        }  
    }  
  
    /** 
     * 将一个换行符写入out中、  
     */  
    public void println(double x) {  
        synchronized (lock) {  
            print(x);  
            println();  
        }  
    }  
  
    /** 
     * 将一个换行符写入out中、  
     */  
    public void println(char x[]) {  
        synchronized (lock) {  
            print(x);  
            println();  
        }  
    }  
  
    /** 
     * 将一个换行符写入out中、  
     */  
    public void println(String x) {  
    synchronized (lock) {  
        print(x);  
        println();  
    }  
    }  
  
    /** 
     * 将一个换行符写入out中、  
     */  
    public void println(Object x) {  
        String s = String.valueOf(x);  
        synchronized (lock) {  
            print(s);  
            println();  
        }  
    }  
  
    /** 
     *  使用指定格式字符串和参数将格式化的字符串写入此 writer 的便捷方法。 
     */  
    public PrintWriter printf(String format, Object ... args) {  
        return format(format, args);  
    }  
  
    /** 
     *  使用指定格式字符串和参数将格式化的字符串写入此 writer 的便捷方法。 
     */  
    public PrintWriter printf(Locale l, String format, Object ... args) {  
        return format(l, format, args);  
    }  
  
    /** 
     *使用指定格式字符串和参数将一个格式化字符串写入此 writer 中。 
     */  
    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;  
    }  
  
    /** 
     *使用指定格式字符串和参数将一个格式化字符串写入此 writer 中。 
     */  
    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;  
    }  
  
    /** 
     * 将一个有序字符序列追加到out中 
     */  
    public PrintWriter append(CharSequence csq) {  
        if (csq == null)  
            write("null");  
        else  
            write(csq.toString());  
            return this;  
    }  
  
      
    /** 
     * 将一个有序字符序列一部分追加到out中  
     */  
    public PrintWriter append(CharSequence csq, int start, int end) {  
        CharSequence cs = (csq == null ? "null" : csq);  
        write(cs.subSequence(start, end).toString());  
            return this;  
    }  
      
    /** 
     * 将一个字符追加到out中 
     */  
    public PrintWriter append(char c) {  
        write(c);  
        return this;  
    }  
}

例子

/**
 * PrintWriter 的示例程序
 */
public class PrintWriterTest {

    public static void main(String[] args) {

        // 下面3个函数的作用都是一样:都是将字母“abcde”写入到文件“file.txt”中。
        // 任选一个执行即可!
        testPrintWriterConstrutor1() ;
        //testPrintWriterConstrutor2() ;
        //testPrintWriterConstrutor3() ;

        // 测试write(), print(), println(), printf()等接口。
        testPrintWriterAPIS() ;
    }

    /**
     * PrintWriter(OutputStream out) 的测试函数
     *
     * 函数的作用,就是将字母“abcde”写入到文件“file.txt”中
     */
    private static void testPrintWriterConstrutor1() {
        final char[] arr={'a', 'b', 'c', 'd', 'e' };
        try {
            // 创建文件“file.txt”的File对象
            File file = new File("file.txt");
            // 创建文件对应FileOutputStream
            PrintWriter out = new PrintWriter(
                    new FileOutputStream(file));
            // 将“字节数组arr”全部写入到输出流中
            out.write(arr);
            // 关闭输出流
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * PrintWriter(File file) 的测试函数
     *
     * 函数的作用,就是将字母“abcde”写入到文件“file.txt”中
     */
    private static void testPrintWriterConstrutor2() {
        final char[] arr={'a', 'b', 'c', 'd', 'e' };
        try {
            File file = new File("file.txt");
            PrintWriter out = new PrintWriter(file);
            out.write(arr);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * PrintWriter(String fileName) 的测试函数
     *
     * 函数的作用,就是将字母“abcde”写入到文件“file.txt”中
     */
    private static void testPrintWriterConstrutor3() {
        final char[] arr={'a', 'b', 'c', 'd', 'e' };
        try {
            PrintWriter out = new PrintWriter("file.txt");
            out.write(arr);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试write(), print(), println(), printf()等接口。
     */
    private static void testPrintWriterAPIS() {
        final char[] arr={'a', 'b', 'c', 'd', 'e' };
        try {
            // 创建文件对应FileOutputStream
            PrintWriter out = new PrintWriter("other.txt");

            // 将字符串“hello PrintWriter”+回车符,写入到输出流中
            out.println("hello PrintWriter");
            // 将0x41写入到输出流中
            // 0x41对应ASCII码的字母'A',也就是写入字符'A'
            out.write(0x41);
            // 将字符串"65"写入到输出流中。
            // out.print(0x41); 等价于 out.write(String.valueOf(0x41));
            out.print(0x41);
            // 将字符'B'追加到输出流中
            out.append('B').append("CDEF");

            // 将"CDE is 5" + 回车  写入到输出流中
            String str = "GHI";
            int num = 5;
            out.printf("%s is %d\n", str, num);

            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行上面的代码,会在源码所在目录生成两个文件“file.txt”和“other.txt”。
file.txt的内容如下:
abcde
other.txt的内容如下:
hello PrintWriter
A65BCDEFGHI is 5

总结

1. PrintWriter是打印字符流,用于将各种java数据一字符串的形式打印到底层字符输出流中,本身不会产生任何IOException,但是可以通过他的一个方法来查看是否抛出异常,可以指定autoFlush,若为true则当调用newLine、println、format方法时都会自动刷新,即将底层字符输出流out中的字符flush到目的地中。

2. PrintWriter与PrintStream很类似、要注意的就是一个是自动刷新的问题,另一个就是PrintStream可以实现将字节写入底层流中write(intb)     write(byte[] b, int off, int len),而PrintWriter没有相关方法来直接将字节写入到out中,还有一点就不管是PrintWriter还是PrintStream,他写入到底层流中的java基础类型或者java对象都是以字符串的形式写入的,所以当我们读取之后要做一些处理,而关于print(Object)只是将Object的表示此对象的Object.toString()这个结果写入到out中,所以读取出来并不是强转一下就可以使用,要想操作java基础类型和对象,应该使用对应的流DataInputStream/DataOutputStream ObjectInputStream/ObjectOutputStream。




版权声明:本文为JAVASCHOOL原创文章,未经本站允许不得转载。