概况
Writer 是一个用于写字符流的抽象类,它将一些相通的写相关操作抽象到此类,方便各种写操作类的实现。一般来说子类只需要实现它的 write、flush 、close 等三个方法,但如果有需要还可以重写 Writer 提供的公共方法。
JDK 在 Writer 的基础上实现了很多有用的 xxxWriter ,包括 BufferedWriter、CharArrayWriter、FilterWriter、OutputStreamWriter、FileWriter、PipedWriter、StringWriter 和 PrintWriter 等等。
继承结构
--java.lang.Object --java.io.Writer复制代码
类定义
public abstract class Writer implements Appendable, Closeable, Flushable复制代码
Writer 被定为 public 且 abstract 的类,实现了 Appendable、Closeable 和 Flushable接口。
Appendable 接口表示字符或字符序列可以被 append,接口定义如下:
public interface Appendable { Appendable append(CharSequence csq) throws IOException; Appendable append(CharSequence csq, int start, int end) throws IOException; Appendable append(char c) throws IOException;}复制代码
Closeable 接口表示 Writer 可以被close,接口定义如下:
public interface Closeable extends AutoCloseable { public void close() throws IOException;}复制代码
Flushable 接口表示 Writer 可以被flush,接口定义如下:
public interface Flushable { void flush() throws IOException;}复制代码
主要属性
private char[] writeBuffer;private static final int WRITE_BUFFER_SIZE = 1024;protected Object lock;复制代码
- writeBuffer 是一个 char[] 类型,表示写缓冲。
- WRITE_BUFFER_SIZE 写缓冲的大小。
- lock 是 Writer 的锁,用于实现同步。
构造方法
有两种构造方法,不带参数时则将自己作为锁,而如果传入了某个 Object 对象则将其作为锁。
protected Writer() { this.lock = this;}protected Writer(Object lock) { if (lock == null) { throw new NullPointerException(); } this.lock = lock;}复制代码
主要方法
write方法
一共有五个 write 方法,其中有一个抽象的 write 方法,可以看到所有 write 方法最终都会调用这个抽象方法,提供给子类处理逻辑的实现。它传入的三个参数,字符数组cbuf、偏移量off和数组长度。
public abstract void write(char cbuf[], int off, int len) throws IOException;复制代码
写入一个 int 类型值时,先通过锁进行同步,再判断 writeBuffer 为 null 则要实例化一个对象,接着将 int 值转成char类型,最后调用抽象 write 方法执行子类逻辑。
写入 char 数组是则直接调用抽象 write 方法。
public void write(int c) throws IOException { synchronized (lock) { if (writeBuffer == null){ writeBuffer = new char[WRITE_BUFFER_SIZE]; } writeBuffer[0] = (char) c; write(writeBuffer, 0, 1); } }public void write(char cbuf[]) throws IOException { write(cbuf, 0, cbuf.length); }复制代码
写入 String 类型数据也有类似的处理,同样是先加锁,再实例化一个 char 数组用于存放写入数据,这里不同的地方在于要根据 String 数据的长度处理,如果小于 WRITE_BUFFER_SIZE 则直接使用 Writer 里面的 writeBuffer 对象,而如果大于 WRITE_BUFFER_SIZE 则需要按照String数据的长度 new 一个 char 数组,但为了节约内存,这个较大的数组使用过后即会被 gc 掉,不必跟着 Writer 的生命周期一直存在。
public void write(String str) throws IOException { write(str, 0, str.length()); }public void write(String str, int off, int len) throws IOException { synchronized (lock) { char cbuf[]; if (len <= WRITE_BUFFER_SIZE) { if (writeBuffer == null) { writeBuffer = new char[WRITE_BUFFER_SIZE]; } cbuf = writeBuffer; } else { cbuf = new char[len]; } str.getChars(off, (off + len), cbuf, 0); write(cbuf, 0, len); } }复制代码
append方法
一共有3个append方法,该方法是 Appendable 接口规定的方法,在实现中其实就是间接调用 write 方法进行写入操作,但不同的是它返回了 this,这样就可以方便地使用 append("xxx").append("yyy")。
public Writer append(char c) throws IOException { write(c); return this; }public Writer append(CharSequence csq) throws IOException { write(String.valueOf(csq)); return this; }public Writer append(CharSequence csq, int start, int end) throws IOException { if (csq == null) csq = "null"; return append(csq.subSequence(start, end)); }复制代码
flush方法
它是一个抽象方法,留给子类实现。此方法用于刷新流,如果 Writer 的缓冲区包含任何字符则马上将其写入目的地。但如果目的地是另外一个流,则继续调用其 flush 方法刷新,所以调用 flush 会刷新 Writer 链的所有缓冲。
此外,如果写入目的地建立在操作系统之上,比如操作系统的文件系统,那么 flush 只保证将缓冲写入操作系统中,而不保证其写入硬盘等物理设备中。
public abstract void flush() throws IOException;复制代码
close方法
它是一个抽象方法,留给子类实现。此方法用于关闭流,关闭之前要先执行 flush 将缓冲刷入目的地。如果某个流已经关闭了还调用 write 或 flush 方法,则将抛出 IOException 。
public abstract void close() throws IOException;复制代码
以下是广告和相关阅读
========广告时间========
鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有需要的朋友可以到 进行预定。感谢各位朋友。
=========================
相关阅读:
欢迎关注: