总结
- Reader虚拟类是用于读取字符流的抽象类
- Reader虚拟类子类必须实现的方法是read(char[], int, int)和close(),但是,大多数子类将重写此处定义的一些方法,以提供更高的效率或附加功能
Reader虚拟类数据结构
public abstract class Reader implements Readable, Closeable {
protected Object lock;
private static final int maxSkipBufferSize = 8192;
private char skipBuffer[] = null;
}
- lock用于同步此流上的操作的对象
- 为了提高效率,字符流对象可以使用自身以外的对象来保护关键部分, 因此,子类应该使用此字段中的对象,而不是同步方法
- 因为同步方法synchronized默认使用当前对象作为锁对象,则其内部所有同步方法都会收到限制,而如果使用同步块只有相同锁对象的代码才会互斥,不能同时运行
- maxSkipBufferSize是最大跳过缓冲区大小,用于跳过一些字符所需的操作,skipBuffer是跳过缓冲区,实际上执行跳过的操作,仍然是要读取数据的,只不过存放在跳过缓冲区
Reader虚拟类方法
构造方法
方法名 | 作用 |
---|
Reader() | 创建一个新的字符流读取器Reader,其关键部分将在读取器本身上同步,即上面的lock对象是当前对象 |
Reader(Object lock) | 创建一个新的字符流读取器Reader,其关键部分将在给定对象上同步,即上面的lock对象这里是给定的lock对象 |
操作方法
方法名 | 作用 |
---|
abstract public int read(char cbuf[], int off, int len) | 读取字符填入字符数组,即从字符数组off下标处开始填入字符,填入len个字符。此方法将阻塞, 直到某些输入可用、发生I/O错误或到达流的结尾。此方法是虚方法,由子类实现,而下面三个读取方法都是调用该虚方法 |
int read(char cbuf[]) | 读取字符填满字符数组,调用上一个虚方法,传入的off是0,len是字符数组cbuf的长度,返回的int是实际读取的字符数量,返回-1表示未读取到字符 |
int read() | 读取一个字符,调用上一个虚方法,创建了一个长度为1的cbuf字符数组,传入的off是0,len是1,然后读取字符填入字符数组后取出cbuff[0]并返回,返回的int是字符的ASCLL码 |
int read(java.nio.CharBuffer target) | 读取字符填满字符缓冲区 target,先获取字符缓冲区target剩余能容纳的字符数,创建该字符数长度的字符数组,调用第一个虚方法,传入的字符数组即是刚刚创建的字符数组,而off为0,len为字符数组长度,读取并填满字符数组后,调用缓冲区的put方法将字符数组中所有字符全部转移到缓冲区 |
其他方法
方法名 | 作用 |
---|
long skip(long n) | 跳过指定数量个字符。此方法将一直阻塞,直到能读取字符、发生I/O错误或到达流的结尾,该方法调用上面的虚方法read,所以跳过效率并不高,并且一次能够跳过的字符数量取决于n和maxSkipBufferSize之间的最小值 |
boolean ready() | 判断此流是否已准备好读取,默认实现总是返回false。子类应该重写此方法 |
boolean markSupported() | 判断此流是否支持mark()操作,默认实现总是返回false。子类应该重写此方法 |
void mark(int readAheadLimit) | 标记流中的当前位置。对reset()的后续调用将尝试将流重新定位到此点, 并非所有字符输入流都支持mark()操作 |
void reset() | 重置流,如果流已标记,则尝试在标记处重新定位。如果未标记流,则尝试以适合于特定流的某种方式将其重置,例如将其重新定位到其起点。并非所有字符输入流都支持reset()操作,有些支持reset(),但不支持mark() |
abstract public void close() | 关闭流并释放与之关联的所有系统资源。关闭流后,进一步调用read(), ready(),mark(), reset(),或skip()将抛出IOException,关闭以前关闭的流没有效果 |