Reader源码解析

3 篇文章 0 订阅
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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值