黑马程序员技术交流社区

标题: 【上海校区】Java8 I/O源码-PrintWriter [打印本页]

作者: 不二晨    时间: 2018-9-7 10:21
标题: 【上海校区】Java8 I/O源码-PrintWriter

今天来学习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/ ... rmatter.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;    }}总结

关于PrintWriter就讲到这里,想了解更多内容请参考

版权声明

作者:潘威威

原文地址:CSDN博客-潘威威的博客-[url]http://blog.csdn.net/panweiwei1994/article/details/78389254[/url]


作者: 不二晨    时间: 2018-9-13 16:06

很不错,受教了




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2