Readable
interface Readable
A Readable是一个字符源
int read(CharBuffer cb) 尝试将字符读入指定的字符缓冲区。
Reader
public abstract class Reader implements Readable, Closeable
用于读取字符流的抽象类
abstract void close() 关闭流并释放与之相关联的任何系统资源。
void mark(int readAheadLimit) 标记流中的当前位置。
boolean markSupported() 告诉这个流是否支持mark()操作。
int read() 读一个字符
int read(char[] cbuf) 将字符读入数组。
abstract int read(char[] cbuf, int off, int len) 将字符读入数组的一部分。
int read(CharBuffer target) 尝试将字符读入指定的字符缓冲区。
boolean ready() 告诉这个流是否准备好被读取。
void reset() 重置流。
long skip(long n) 跳过字符
具体读取操作在子类实现
abstract public int read(char cbuf[], int off, int len) throws IOException;
skip(long n) 读取的时候跳过n个字符
private static final int maxSkipBufferSize = 8192;// 最大可以跳过的字符集
public long skip(long n) throws IOException {
int nn = (int) Math.min(n, maxSkipBufferSize);
synchronized (lock) {
if ((skipBuffer == null) || (skipBuffer.length < nn))
skipBuffer = new char[nn]; //new 一个要跳过多少字符的容器
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;
}
}
InputStreamReader
public class InputStreamReader extends Reader
InputStreamReader是从字节流到字符流的桥
String getEncoding() 返回此流使用的字符编码的名称。
int read()
private final StreamDecoder sd; //真正处理类
public int read() throws IOException {
return sd.read();
}
FileReader
public class FileReader extends InputStreamReader
public FileReader(File file)
public FileReader(File file) throws FileNotFoundException {
super(new FileInputStream(file));
}
没有实现类 全都使用的是父类 InputStreamReader 的方法
BufferedReader
public class BufferedReader extends Reader
从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。
Stream<String> lines() 返回一个 Stream ,其元素是从这个 BufferedReader读取的行。
String readLine() 读一行文字。
private char cb[]; //缓存字符的数组
private int nChars, nextChar;//缓存字符的个数 下一个字符的下标
private static final int INVALIDATED = -2;//标记失效常量
private static final int UNMARKED = -1;// 没有标记
private int markedChar = UNMARKED;// 标记位置的下标
private int readAheadLimit = 0; //标记长度上限
int read()
public int read() throws IOException {
synchronized (lock) {
ensureOpen();
for (;;) {
if (nextChar >= nChars) {
fill();
if (nextChar >= nChars)
return -1;
}
if (skipLF) {
skipLF = false;
if (cb[nextChar] == '\n') {
nextChar++;
continue;
}
}
return cb[nextChar++];
}
}
}
void fill()
private void fill() throws IOException {
int dst;
if (markedChar <= UNMARKED) { // 没有标记
dst = 0;
} else { //以下情况都有标记
int delta = nextChar - markedChar;
if (delta >= readAheadLimit) { // 超过标记上限
markedChar = INVALIDATED; //设置标记失效
readAheadLimit = 0;
dst = 0;
} else { // 没有超过标记上限
if (readAheadLimit <= cb.length) { //标记上限比数组长度小
// 数据拷贝 从标记位置开始 缓存
System.arraycopy(cb, markedChar, cb, 0, delta); //
markedChar = 0;
dst = delta;
} else { // 标记上限比数组长度大
int nlength = cb.length * 2;
if (nlength > readAheadLimit) {
nlength = readAheadLimit;
}
char ncb[] = new char[nlength]; //扩容缓存数组
System.arraycopy(cb, markedChar, ncb, 0, delta);
cb = ncb;
markedChar = 0;
dst = delta;
}
nextChar = nChars = delta;
}
}
int n;
do {
n = in.read(cb, dst, cb.length - dst); // 读取数据 由装饰对象实现
} while (n == 0);
if (n > 0) {
nChars = dst + n;
nextChar = dst;
}
}
String readLine(boolean ignoreLF)
String readLine(boolean ignoreLF) throws IOException {
StringBuffer s = null;
int startChar;
synchronized (lock) {
ensureOpen();
boolean omitLF = ignoreLF || skipLF;
bufferLoop: //跳出for循环的标签
for (;;) {
if (nextChar >= nChars) //
fill();
if (nextChar >= nChars) {
if (s != null && s.length() > 0)
return s.toString();
else
return null;
}
boolean eol = false;
char c = 0;
int i;
/* Skip a leftover '\n', if necessary */
if (omitLF && (cb[nextChar] == '\n'))
nextChar++;
skipLF = false;
omitLF = false;
charLoop:
for (i = nextChar; i < nChars; i++) {
c = cb[i];
if ((c == '\n') || (c == '\r')) { //查找 换行符
eol = true;
break charLoop;
}
}
startChar = nextChar;
nextChar = i;
if (eol) {
String str;
if (s == null) {
str = new String(cb, startChar, i - startChar);
} else {
s.append(cb, startChar, i - startChar);
str = s.toString();
}
nextChar++;
if (c == '\r') {
skipLF = true;
}
return str;
}
if (s == null)
s = new StringBuffer(defaultExpectedLineLength);
s.append(cb, startChar, i - startChar);
}
}
}
void mark(int readAheadLimit) 标记字符当前位置
// readAheadLimit 标记字符上限(最多标记字符的长度)
public void mark(int readAheadLimit) throws IOException {
synchronized (lock) {
ensureOpen();
this.readAheadLimit = readAheadLimit;
markedChar = nextChar;
markedSkipLF = skipLF;
}
}
void reset() 恢复到标记字符位置
public void reset() throws IOException {
synchronized (lock) {
ensureOpen();
if (markedChar < 0)
throw new IOException((markedChar == INVALIDATED)
? "Mark invalid"
: "Stream not marked");
nextChar = markedChar; //
skipLF = markedSkipLF; //
}
}
CharArrayReader
public class CharArrayReader extends Reader
protected char[] buf 字符缓冲区。
protected int count 这个缓冲区结束的索引。
protected int markedPos 标记在缓冲区中的位置。
protected int pos 当前的缓冲位置。
int read()
public int read() throws IOException {
synchronized (lock) {
ensureOpen();
if (pos >= count) //读完了
return -1;
else
return buf[pos++]; //返回字符
}
}
int read(char b[], int off, int len)
public int read(char b[], int off, int len) throws IOException {
synchronized (lock) {
....
if (pos + len > count) {
len = count - pos;
}
if (len <= 0) {
return 0;
}
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}
}