Reader源码解析

mac2024-01-29  38

package java.io; public abstract class Reader implements Readable, Closeable { //用于同步操作此流的线程 protected Object lock; //把自己的实例作为锁对象 protected Reader() { this.lock = this; } //把输入的Object作为锁对象 protected Reader(Object lock) { if (lock == null) { throw new NullPointerException(); } this.lock = lock; } /** * 此方法可以把字符输入流的数据保存到缓冲区中。 * 返回实际存进缓冲区的数量,如果为-1表示已经到底了。 * 此方法可能会抛出以下三个异常: * 空指针异常,如果target是null。 * IO异常 * 缓冲区只读异常,如果target是只读的,无法写。 * @since 1.5 */ public int read(java.nio.CharBuffer target) throws IOException { //获得缓冲区还可以缓冲字符的长度 int len = target.remaining(); char[] cbuf = new char[len]; //n为实际读取字符的数量 int n = read(cbuf, 0, len); //如果有读取,就把读取到的字符存进字符缓冲区中。 if (n > 0) target.put(cbuf, 0, n); return n; } //读取一个字符,返回字符强转int后的值。 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; //一次最大可跳过的字符数 private static final int maxSkipBufferSize = 8192; //用于储存已经跳过的字符 private char skipBuffer[] = null; /** * 跳过指定的字符数。这个方法将会阻塞直到字符是有效的、发生IO异常、或者输入流已经到* * 底了。 * @param n 需要跳过的字符数 * @return 返回实际跳过的字符数 */ public long skip(long n) throws IOException { if (n < 0L)//跳过的字符数不能小于0,不然会出异常。 throw new IllegalArgumentException("skip value is negative"); //nn为一次跳过的字符数,不能大于maxSkipBufferSize。 int nn = (int) Math.min(n, maxSkipBufferSize); synchronized (lock) {//做同步锁,防止多线程访问的时候出现奇怪的逻辑现象。 //如果skipBuffer为空,或者长度小于nn if ((skipBuffer == null) || (skipBuffer.length < nn)) //就会重新创建一个nn长度的字符数组 skipBuffer = new char[nn]; long r = n;//用于储存还需要跳过的字符数 while (r > 0) { //注意这里的(int)Math.min(r, nn),和前面的(int) Math.min(n, maxSkipBufferSize)搭配。 int nc = read(skipBuffer, 0, (int)Math.min(r, nn)); //如果输入流已经到底了,直接跳出循环。 if (nc == -1) break; //减去已经跳过的字符数 r -= nc; } //需要跳过的字符数-还需跳过的字符数=实际跳过的字符数。 return n - r; } } /** * 判断这个字节流是否能被读。 * 如果返回True,则保证下次调用read()方法的时候不阻塞输入,否则返回False。 * 记住,返回False不保证下次调用read()方法的时候会被阻塞。 */ public boolean ready() throws IOException { 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"); } /** *关闭输入流与相关的资源,这会导致read()\ready()\mark() *\reset()\skip()抛出IO异常,关闭已经关闭的资源是没有任何效果的。 */ abstract public void close() throws IOException; }
最新回复(0)