目录
字段maxSkipBufferSize,字段skipBuffer,skip方法
方法ready,markSupported,mark,reset,close
简介
/**
* 用于读取字符流的抽象类。子类必须实现的唯一方法是read(char[], int, int)和close()。
* 然而,大多数子类将重写这里定义的一些方法,以提供更高的效率、额外的功能,或者同时提供这两种功能。
*
*
* @see BufferedReader
* @see LineNumberReader
* @see CharArrayReader
* @see InputStreamReader
* @see FileReader
* @see FilterReader
* @see PushbackReader
* @see PipedReader
* @see StringReader
* @see Writer
*
* @author Mark Reinhold
* @since JDK1.1
*/
public abstract class Reader implements Readable, Closeable
字段lock,两个构造函数
/**
* 用于同步此流上的操作的对象。
* 为了高效,字符流对象可以使用其他对象来保护临界区。
* 因此,子类应该使用该对象,而不是用this或者synchronized方法。
*/
protected Object lock;
/**
* 创建一个新的字符流读取器,它的临界区是读取器自己。
*/
protected Reader() {
this.lock = this;
}
/**
* 创建一个新的字符流读取器,它的临界区是给定的对象。
*
* @param lock The Object to synchronize on.
*/
protected Reader(Object lock) {
if (lock == null) {
throw new NullPointerException();
}
this.lock = lock;
}
4个read方法
/**
* 尝试将字符读入指定的字符缓冲区。
* 缓冲区用作字符存储库:
* 所做的更改仅是put操作的结果。
* 不执行缓冲区的flip或者rewind。
*
* @param target the buffer to read characters into
* @return The number of characters added to the buffer, or
* -1 if this source of characters is at its end
* @throws IOException if an I/O error occurs
* @throws NullPointerException if target is null
* @throws java.nio.ReadOnlyBufferException if target is a read only buffer
* @since 1.5
*/
public int read(java.nio.CharBuffer target) throws IOException {
// 创建一个char数组,长度为target剩余的空间
int len = target.remaining();
char[] cbuf = new char[len];
// 调用read方法,填入cbuf的0,长度为len
int n = read(cbuf, 0, len);
// 如果读取到了数据,从cbuf往target填充数据
if (n > 0)
target.put(cbuf, 0, n);
// 返回读取到的char数量
return n;
}
/**
* 读取单个字符。此方法将阻塞,直到出现可用字符、发生I/O错误或到达流的末尾为止。
*
* <p>想要支持高效单字符输入的子类应该重写这个方法。
*
* @return The character read, as an integer in the range 0 to 65535
* (<tt>0x00-0xffff</tt>), or -1 if the end of the stream has
* been reached
*
* @exception IOException If an I/O error occurs
*/
public int read() throws IOException {
char cb[] = new char[1];
if (read(cb, 0, 1) == -1)
return -1;
else
return cb[0];
}
/**
* 将字符读入数组。
* 此方法将阻塞,直到一些可用的输入、发生I/O错误或到达流的末尾为止。
*
* @param cbuf Destination buffer
*
* @return The number of characters read, or -1
* if the end of the stream
* has been reached
*
* @exception IOException If an I/O error occurs
*/
public int read(char cbuf[]) throws IOException {
return read(cbuf, 0, cbuf.length);
}
/**
* 将字符读入数组的一部分。
* 这个方法将被阻塞,直到有一些输入可用、出现I/O错误或到达流的末尾。
* 注意:该方法一定要实现
*
* @param cbuf Destination buffer
* @param off Offset at which to start storing characters
* @param len Maximum number of characters to read
*
* @return The number of characters read, or -1 if the end of the
* stream has been reached
*
* @exception IOException If an I/O error occurs
*/
abstract public int read(char cbuf[], int off, int len) throws IOException;
字段maxSkipBufferSize,字段skipBuffer,skip方法
/** 最大跳跃缓存大小 8192*/
private static final int maxSkipBufferSize = 8192;
/** 跳跃缓冲区,null直到分配*/
private char skipBuffer[] = null;
/**
* 跳过字符。此方法将阻塞,直到出现一些可用字符、发生I/O错误或到达流的末尾为止。
*
* @param n 跳过的字符数目
*
* @return The number of characters actually skipped
*
* @exception IllegalArgumentException If <code>n</code> is negative.
* @exception IOException If an I/O error occurs
*/
public long skip(long n) throws IOException {
if (n < 0L)
throw new IllegalArgumentException("skip value is negative");
// 一次跳过min(n,maxSkipBufferSize),如果没有调到n,就多跳几次
int nn = (int) Math.min(n, maxSkipBufferSize);
synchronized (lock) {
if ((skipBuffer == null) || (skipBuffer.length < nn))
skipBuffer = new char[nn];
long r = n;
// r为还要跳过的字符数
while (r > 0) {
// 通过调用read方法,读入skipBuffer来跳过
int nc = read(skipBuffer, 0, (int)Math.min(r, nn));
// 如果某次读取数为-1,跳出循环
if (nc == -1)
break;
r -= nc;
}
return n - r;
}
}
方法ready,markSupported,mark,reset,close
/**
* 告知该流是否已准备好读取。
*
* @return 如果保证下一个read()不会阻塞输入,则为True,否则为false。
* 注意,返回false并不保证下一个读取将阻塞。
*
* @exception IOException If an I/O error occurs
*/
public boolean ready() throws IOException {
return false;
}
/**
* 告知此流是否支持mark()操作。结果总是返回false。子类应该重写这个方法。
*
* @return true if and only if this stream supports the mark operation.
*/
public boolean markSupported() {
return false;
}
/**
* 标记流中的当前位置。对reset()的后续调用将尝试将流重新定位到此处。
* 并非所有字符输入流都支持mark()操作。
*
* @param readAheadLimit 在保留标记的同时限制可能丢失的字符的数量。
* 在读取了这么多字符之后,尝试重置流可能会失败。
*
* @exception IOException If the stream does not support mark(),
* or if some other I/O error occurs
*/
public void mark(int readAheadLimit) throws IOException {
throw new IOException("mark() not supported");
}
/**
* 重置。如果流已被标记,则尝试在标记处重新定位它。
* 如果流没有被标记,那么尝试以某种适合于特定流的方式重置它,例如将其重新定位到起始点。
* 不是所有字符输入流都支持reset()操作,而且有些支持reset()不支持mark()。
*
* @exception IOException If the stream has not been marked,
* or if the mark has been invalidated,
* or if the stream does not support reset(),
* or if some other I/O error occurs
*/
public void reset() throws IOException {
throw new IOException("reset() not supported");
}
/**
* 关闭流并释放与之关联的任何系统资源。
* 一旦流被关闭,进一步的read()、ready()、mark()、reset()或skip()调用将抛出一个IOException。
* 关闭以前关闭的流没有任何效果。
*
* @exception IOException If an I/O error occurs
*/
abstract public void close() throws IOException;