JavaIO -- Reader 和 Writer
一、简介
设计Reader和Writer继承层次结构主要是为了国际化。InputStream和OutStream流继承层次结构仅支持8位字节流,并不能很好的处理16位的Unicode字符。由于Unicode用于字符国际化(java本身的char也是16位的Unicode),所以添加了Reader和Writer继承层次结构就是为了所有的I/O操作中都支持Unicode。另外,字符流(Reader、Writer)比字节流(InputSteam、OutStream)更快。
Reader 和 Writer对于字符流的输入和输出也是作为协议的存在。
二、Reader(输入)
基本和InputStream差不多,只不过它是操作字符流的。
public abstract class Reader implements Readable, Closeable { //为了提高效率,字流对象可以使用除自身之外的对象来保护临界段。因此,子类应该在这个字段中使用对象,而不是this或同步方法。 protected Object lock; protected Reader() { this.lock = this; } protected Reader(Object lock) { if (lock == null) { throw new NullPointerException(); } this.lock = lock; } // public int read(java.nio.CharBuffer target) throws IOException { int len = target.remaining(); char[] cbuf = new char[len]; int n = read(cbuf, 0, len); if (n > 0) target.put(cbuf, 0, n); return n; } //读取单个字符 public int read() throws IOException { char cb[] = new char[1]; if (read(cb, 0, 1) == -1) return -1; else return cb[0]; } //将字符读入数组 public int read(char cbuf[]) throws IOException { return read(cbuf, 0, cbuf.length); } //从off开始,读取len长度的数组,读入数组中 abstract public int read(char cbuf[], int off, int len) throws IOException; //可跳过字符数量的最大值 private static final int maxSkipBufferSize = 8192; //存储跳过的字符数组 private char skipBuffer[] = null; //跳过字符。返回实际跳过的字符数 public long skip(long n) throws IOException { if (n < 0L) throw new IllegalArgumentException("skip value is negative"); int nn = (int) Math.min(n, maxSkipBufferSize); //获取最小值 synchronized (lock) { //加锁 if ((skipBuffer == null) || (skipBuffer.length < nn)) //数组不为空 || 数组长度小于跳过的字符数 skipBuffer = new char[nn]; long r = n; while (r > 0) { int nc = read(skipBuffer, 0, (int)Math.min(r, nn)); if (nc == -1) break; r -= nc; } return n - r; } } //表示此流是否已准备好读取。 public boolean ready() throws IOException { return false; } /表示该流是否支持mark()操作 public boolean markSupported() { return false; } //标记当前流中的位置。 public void mark(int readAheadLimit) throws IOException { throw new IOException("mark() not supported"); } //重置 public void reset() throws IOException { throw new IOException("reset() not supported"); } //关闭流并释放与之关联的任何系统资源。 abstract public void close() throws IOException; }
三、Writer(输出)
public abstract class Writer implements Appendable, Closeable, Flushable { //用于保存字符串和单个字符的写的临时缓冲区 private char[] writeBuffer; //缓存区大小 private static final int WRITE_BUFFER_SIZE = 1024; protected Object lock; protected Writer() { this.lock = this; } protected Writer(Object lock) { if (lock == null) { throw new NullPointerException(); } this.lock = lock; } //写入一个字符 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); } //写入字符数组的一部分。 abstract public void write(char cbuf[], int off, int len) throws IOException; //写一个字符串。 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 { //如果长度大于缓存区的长度,重新新建一个len长度的字符数组。但是不要永久地分配非常大的缓冲区。 cbuf = new char[len]; } str.getChars(off, (off + len), cbuf, 0);//获取str字符串 从off开始,长度为len的字符串 write(cbuf, 0, len); } } //将指定的字符序列追加到写入器。 public Writer append(CharSequence csq) throws IOException { if (csq == null) write("null"); else write(csq.toString()); return this; } //向写入器追加指定字符序列的子序列。 public Writer append(CharSequence csq, int start, int end) throws IOException { CharSequence cs = (csq == null ? "null" : csq); write(cs.subSequence(start, end).toString()); return this; } //将指定的字符附加到写入器。 public Writer append(char c) throws IOException { write(c); return this; } //刷新流 abstract public void flush() throws IOException; //关闭流 abstract public void close() throws IOException; }