您的位置:首页 > 编程语言 > Java开发

【Java部分源码分析之io篇】5.Reader

2017-07-27 00:00 316 查看
之前分析的都是字节的输入输出流,现在开始来看看字符的输入输出流。

Reader是字符输入流,与之对应的字节输入流是InputStream,后面会讲到有一个类利用字节输入流构建字符输入流,这个类就是InputStreamReader。与InputStream一样,Reader也是一个抽象类。它有一个成员变量lock,这个lock使得在这个流上的操作在多线程环境下可以安全的执行。来看一下这个成员变量。

/**
* The object used to synchronize operations on this stream.  For
* efficiency, a character-stream object may use an object other than
* itself to protect critical sections.  A subclass should therefore use
* the object in this field rather than <tt>this</tt> or a synchronized
* method.
*/
protected Object lock;

接下来看一下它的两个构造方法。

protected Reader() {
this.lock = this;
}
protected Reader(Object lock) {
if (lock == null) {
throw new NullPointerException();
}
this.lock = lock;
}

两个构造方法没什么看头,都是在给lock赋值。

接下来看一下read方法。

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);
}
abstract public int read(char cbuf[], int off, int len) throws IOException;

可以看到最下面的抽象read方法没有任何实现,这个read方法是留到子类中实现的,一般来说,子类中的read方法是调用的本地方法,用native定义。其他三个重载read方法都是调用最后一个read方法,第一个还比较特殊,它的参数是NIO的一个对象CharBuffer,以后我们会讲解到这个对象的。

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;
}
}

接下来看一下所有流操作都会有的skip,就是在流上往前走的字符数。这里定义了一个最大跳跃字符数为8192,也就是说一次跳跃最大可以跳8192个字符。同时skip在方法体内用了synchronized来控制,在多线程环境下也是安全的。如果跳跃小于8192个字符,则返回跳跃的字符数。

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;

上面两个方法是比较少用,mark的作用用来标记输入流的一个位置,这样调用reset之后,输入流就能再次回到标记的位置,readlimit代表只能从输入流读取的数目。

close是个抽象方法,具体实现是在子类中实现。一般来说也是调用在JVM层面实现的本地方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  源码分析 Reader