Java 日看一类(46)之IO包中的PrintStream

该类继承自FilterOutputStream,完成了Appendable,Closeable接口

该类引入了如下包:

import java.util.Formatter;
import java.util.Locale;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;



该类的类头注释如下:

/**
 * A <code>PrintStream</code> adds functionality to another output stream,
 * namely the ability to print representations of various data values
 * conveniently.  Two other features are provided as well.  Unlike other output
 * streams, a <code>PrintStream</code> never throws an
 * <code>IOException</code>; instead, exceptional situations merely set an
 * internal flag that can be tested via the <code>checkError</code> method.
 * Optionally, a <code>PrintStream</code> can be created so as to flush
 * automatically; this means that the <code>flush</code> method is
 * automatically invoked after a byte array is written, one of the
 * <code>println</code> methods is invoked, or a newline character or byte
 * (<code>'\n'</code>) is written.
 *
 * <p> All characters printed by a <code>PrintStream</code> are converted into
 * bytes using the platform's default character encoding.  The <code>{@link
 * PrintWriter}</code> class should be used in situations that require writing
 * characters rather than bytes.
 *
 * @author     Frank Yellin
 * @author     Mark Reinhold
 * @since      JDK1.0
 */

大意如下:

PrintStream相对于其他的输出流增加了一些实用功能,即高效方便地打印出多种类型数据的表示形式

同时也提供两种额外的功能

不同于其他输出流,PrintStream从不抛出IOException;作为替代,异常情况下仅仅设置一个内部的标志位

这个标志位可以被checkError方法检测

可供选择的功能:PrintStream可以被创建为自动刷新模式,这种情况下意味着flush方法将会在byte数组被写入,或println方法被调用后,或者是被写入一个新行符(或者byte'\n')后自动调用

全部被PrintStream打印出的字符将会使用底层系统默认的字符解码方式解码为byte

PrintWriter类应该在更需要写出字符类的情况下使用



该类含有如下的成员变量:

自动刷新标志位

private final boolean autoFlush;

当前流是否报错标志位

private boolean trouble = false;

格式控制

private Formatter formatter;

内部输出流(文本和字符输出流)

private BufferedWriter textOut;
private OutputStreamWriter charOut;

关闭标志位(防止多次关闭

private boolean closing = false;


该类含有如下的成员方法:

在PrintStream初始化前先显示声明requireNonNull,避免系统创建额外的依赖关系(其他的默认方法),返回对象或者空指针信息

private static <T> T requireNonNull(T obj, String message) {
    if (obj == null)
        throw new NullPointerException(message);
    return obj;
}

返回字符串所使用字符集

private static Charset toCharset(String csn)
    throws UnsupportedEncodingException//使用编码方式不支持
{
    requireNonNull(csn, "charsetName");//判定是否为空
    try {
        return Charset.forName(csn);//返回字符集名称
    } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) {
        // UnsupportedEncodingException should be thrown
        throw new UnsupportedEncodingException(csn);
    }
}

私有构造函数(指定自动刷新功能和输出流)

private PrintStream(boolean autoFlush, OutputStream out) {
    super(out);
    this.autoFlush = autoFlush;
    this.charOut = new OutputStreamWriter(this);//注意这里的封装嵌套
    this.textOut = new BufferedWriter(charOut);
}

私有构造函数(指定自动刷新功能、输出流、以及字符集

private PrintStream(boolean autoFlush, OutputStream out, Charset charset) {
    super(out);
    this.autoFlush = autoFlush;
    this.charOut = new OutputStreamWriter(this, charset);//指定输出流的字符集
    this.textOut = new BufferedWriter(charOut);
}

私有构造函数(上个构造函数相同)

private PrintStream(boolean autoFlush, Charset charset, OutputStream out)
    throws UnsupportedEncodingException
{
    this(autoFlush, out, charset);
}

构造函数(非自动

public PrintStream(OutputStream out) {
    this(out, false);
}

构造函数(指定自动属性

public PrintStream(OutputStream out, boolean autoFlush) {
    this(autoFlush, requireNonNull(out, "Null output stream"));
}

构造函数(指定了编码字符集名称

public PrintStream(OutputStream out, boolean autoFlush, String encoding)
    throws UnsupportedEncodingException
{
    this(autoFlush,
         requireNonNull(out, "Null output stream"),
         toCharset(encoding));//获得字符串指定的字符集对象
}

构造函数(指定了写出文件路径,内嵌文件输出流,不自动刷新)

public PrintStream(String fileName) throws FileNotFoundException {
    this(false, new FileOutputStream(fileName));
}

构造函数(指定写出文件路径,不自动刷新,指定字符集

public PrintStream(String fileName, String csn)
    throws FileNotFoundException, UnsupportedEncodingException
{
    // ensure charset is checked before the file is opened
    this(false, toCharset(csn), new FileOutputStream(fileName));
}

构造函数(指定文件,内嵌文件输出流,非自动刷新

public PrintStream(File file) throws FileNotFoundException {
    this(false, new FileOutputStream(file));
}

构造函数(指定文件和字符集,非自动刷新

public PrintStream(File file, String csn)
    throws FileNotFoundException, UnsupportedEncodingException
{
    // ensure charset is checked before the file is opened
    this(false, toCharset(csn), new FileOutputStream(file));
}

判断流有效状态

private void ensureOpen() throws IOException {
    if (out == null)
        throw new IOException("Stream closed");
}

刷新输出流

public void flush() {
    synchronized (this) {
        try {
            ensureOpen();
            out.flush();
        }
        catch (IOException x) {
            trouble = true;
        }
    }
}

关闭输出流

public void close() {
    synchronized (this) {
        if (! closing) {
            closing = true;
            try {
                textOut.close();
                out.close();
            }
            catch (IOException x) {
                trouble = true;
            }
            textOut = null;//清空含有的资源,通过垃圾回收机制自动释放
            charOut = null;
            out = null;
        }
    }
}

检测错误信息

public boolean checkError() {
    if (out != null)
        flush();//清空输出流
    if (out instanceof java.io.PrintStream) {//检测内嵌输出流类型
        PrintStream ps = (PrintStream) out;
        return ps.checkError();
    }
    return trouble;//返回错误标识
}

设置错误标识

protected void setError() {
    trouble = true;
}

清除错误标识

protected void clearError() {
    trouble = false;
}

写出单个字节

public void write(int b) {
    try {
        synchronized (this) {
            ensureOpen();
            out.write(b);
            if ((b == '\n') && autoFlush)//如果当前输入为新行符且开启自动刷新
                out.flush();
        }
    }
    catch (InterruptedIOException x) {//IO中断异常
        Thread.currentThread().interrupt();//中断当前线程
    }
    catch (IOException x) {
        trouble = true;
    }
}

写出字节数组

public void write(byte buf[], int off, int len) {
    try {
        synchronized (this) {
            ensureOpen();
            out.write(buf, off, len);
            if (autoFlush)
                out.flush();
        }
    }
    catch (InterruptedIOException x) {
        Thread.currentThread().interrupt();
    }
    catch (IOException x) {
        trouble = true;
    }
}

私有写出字节数组

private void write(char buf[]) {
    try {
        synchronized (this) {
            ensureOpen();
            textOut.write(buf);//写入缓冲区
            textOut.flushBuffer();//刷新缓冲区
            charOut.flushBuffer();
            if (autoFlush) {
                for (int i = 0; i < buf.length; i++)
                    if (buf[i] == '\n')
                        out.flush();//从FilterOutputStream继承下来的内嵌输出流,刷新输出流
            }
        }
    }
    catch (InterruptedIOException x) {
        Thread.currentThread().interrupt();
    }
    catch (IOException x) {
        trouble = true;
    }
}

写出字符串

private void write(String s) {
    try {
        synchronized (this) {
            ensureOpen();
            textOut.write(s);
            textOut.flushBuffer();
            charOut.flushBuffer();
            if (autoFlush && (s.indexOf('\n') >= 0))
                out.flush();
        }
    }
    catch (InterruptedIOException x) {
        Thread.currentThread().interrupt();
    }
    catch (IOException x) {
        trouble = true;
    }
}

写出新行符(换行)

private void newLine() {
    try {
        synchronized (this) {
            ensureOpen();
            textOut.newLine();
            textOut.flushBuffer();
            charOut.flushBuffer();
            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(String.valueOf(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));
}

默认打印方法,打印换行符

public void println() {
    newLine();
}

打印bool类后接新行符

public void println(boolean x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

打印字符类后接新行符

public void println(char x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

打印整形后接新行符

public void println(int x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

打印长整型后接新行符

public void println(long x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

打印浮点型后接新行符

public void println(float x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

打印双精度型后接新行符

public void println(double x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

打印字符数组后接新行符

public void println(char x[]) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

打印字符串后接新行符

public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

打印对象后接新行符

public void println(Object x) {
    String s = String.valueOf(x);
    synchronized (this) {
        print(s);
        newLine();
    }
}

输出指定格式的一串对象数据

public PrintStream printf(String format, Object ... args) {
    return format(format, args);
}

输出指定格式的一串对象数据(包含地区敏感

public PrintStream printf(Locale l, String format, Object ... args) {
    return format(l, format, args);
}

使用指定格式字符串和参数将格式化字符写入该字符串(默认地区

public PrintStream format(String format, Object ... args) {
    try {
        synchronized (this) {
            ensureOpen();
            if ((formatter == null)
                || (formatter.locale() != Locale.getDefault()))//检测指定格式有效性
                formatter = new Formatter((Appendable) this);//限制绑定当前流
            formatter.format(Locale.getDefault(), format, args);//格式化当前字符串,并写入
        }
    } catch (InterruptedIOException x) {
        Thread.currentThread().interrupt();
    } catch (IOException x) {
        trouble = true;
    }
    return this;//返回当前流
}

指定格式和地区写入字符串

public PrintStream format(Locale l, String format, Object ... args) {
    try {
        synchronized (this) {
            ensureOpen();
            if ((formatter == null)
                || (formatter.locale() != l))
                formatter = new Formatter(this, l);
            formatter.format(l, format, args);
        }
    } catch (InterruptedIOException x) {
        Thread.currentThread().interrupt();
    } catch (IOException x) {
        trouble = true;
    }
    return this;
}

向流中增加字符序列

public PrintStream append(CharSequence csq) {
    if (csq == null)
        print("null");
    else
        print(csq.toString());
    return this;
}

添加字符序列特定段

public PrintStream append(CharSequence csq, int start, int end) {
    CharSequence cs = (csq == null ? "null" : csq);
    write(cs.subSequence(start, end).toString());
    return this;
}

添加单个字符

public PrintStream append(char c) {
    print(c);
    return this;
}



该类写入方式很简单,十分清晰,需要注意多层流的功能封装,以及打印时的及时输出。但是由于每次打印都要刷新,实际写出效率并不高,使用时需要注意。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值