JavaIO -- Reader 和 Writer

一、简介

  设计ReaderWriter继承层次结构主要是为了国际化。InputStreamOutStream流继承层次结构仅支持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;

}
posted @ 2019-11-09 15:20  王大军  阅读(337)  评论(0编辑  收藏  举报