Java 日看一类(47)之IO包中的PrintWriter

该类继承自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

猜你喜欢

转载自blog.csdn.net/github_37666068/article/details/80092277