像BufferedInputStream为FileInputStream提供了缓冲区同样,BufferedReader为InputStreamReader提供了缓冲区。通常状况下,全部的读取都是先从下层输入流读取到缓冲区,而后再从缓冲区读取到目标数组,除非出现要读取的长度超过了缓冲区大小且缓冲区没有有效数据和有效mark,能够直接从下层输入流读取字符。数组
来看一下这个类的头部注释:从字符输入流读取文本,缓冲字符来提供高效地读取字符、数组和行。缓冲区的大小多是指定的或者是默认大小,默认大小对于大部分状况足够大了。通常来讲,Reader的每个读取请求引发一个下层的字节或者字符输入流的读取请求。因此建议用BufferedReader来包裹一个read方法花费大的Reader,好比FileReaders和InputStreamReaders。例如 BufferedReader in = new BufferedReader(new FileReader("foo.in"));将会缓存从特定文件来的输入。没有缓冲,每一次调用read()或者readLine()可能引发从文件读取字节,转换为字符后返回,这样效率不高。使用DataInputStreams进行文本输入的程序能够经过替换每个DataInputStream为合适的BufferedReader进行局部化。缓存
前面已经解释过为何能够经过从文件读取大块内容存储到内存缓冲区来提升总体读取速度,BufferedReader就是字符缓冲输入流。它提供了一个字符数组来做为缓冲区,默认大小是8K,在构造时初始化,fill()方法可能会出现须要从新分配一个更大数组的状况。从构造函数和内部变量中,咱们能够看到它也具备内部包裹的下层输入流而且须要是Reader及其子类。函数
/** * 下层输入流 */ private Reader in; /** * 缓冲区 */ private char cb[]; /** * 最后一个有效字符的位置 */ private int nChars; /** * 下一个要读取的字符位置 */ private int nextChar; private static final int INVALIDATED = -2; private static final int UNMARKED = -1; /** * 标记的位置,小于等于-1时表明不存在mark */ private int markedChar = UNMARKED; private int readAheadLimit = 0; /* 只有markedChar > 0时是有效的 */ /** 若是下一个字符是换行符,跳过它 */ private boolean skipLF = false; /** 设定mark时skipLF的标记 */ private boolean markedSkipLF = false; private static int defaultCharBufferSize = 8192; private static int defaultExpectedLineLength = 80; /** * 建立一个缓冲字符输入流使用一个指定大小的输入缓冲区 */ public BufferedReader(Reader in, int sz) { super(in); if (sz <= 0) throw new IllegalArgumentException("Buffer size <= 0"); this.in = in; cb = new char[sz]; nextChar = nChars = 0; } /** * 建立一个缓冲字符输入流使用一个默认大小8K的输入缓冲区 */ public BufferedReader(Reader in) { this(in, defaultCharBufferSize); }
ensureOpen这个内部方法的做用就是检查流有没有被关闭,标志是下层输入流为nullthis