结合一句代码了解这个类图
BufferedReader bufferedReader = new BufferedReader(new FileReader(inputFile))
new了一个BufferedReader。输入是一个FileReader。
也就是BufferedReader里面的in变量就是FileReader。
另外几个关联的属性:cb,nchars,nextchar等
看看cb的定义:char cb[],BufferedReader是缓冲字符输入流。cb就是字符缓冲区,默认8192长度。作用是存储一次和操作系统io交互之后,读取到的8192个字符数据。
而nchars的含义是当前cb中的字符总数,nextchar是下一个读取的数据的数组下标。
当调用bufferedReader.read()时候看下是怎么工作的
缓冲区字符数组取数据的简单算法描述:
1、当第一次读取一个字符的时候,nextchar =0; nchars=0;这是什么含义,这就是说cb字符数组中没有数据,那就调用FileReader读取一组字符数组到cb中。同时修改nchars=8192;返回cb[extchar++]
2、当读取第二个字符的时候,nextchar=1,nchars=8192。那直接返回cb[nextchar];
3、因为nextchar是从0开始的,当读取完字符缓冲去8192个字符后,下一次读取的时候nextchar=8192。这个时候发现nextchar大于等于nchars=8192;就说明已经读取完缓冲区所有数据了。要重新调用FileReader从操作系统文件中读取下一组数据放到字符缓冲区cb中,并且将nextchar设置为0,nchars=8192;
4、不断往复
看上面类图FileReader是InputStreamReader的子类,InputStreamReader有属性sd,就是StreamDecoder。
FileReader.read()调用的是InputStreamReader的read()方法,如下,可以看到实际上调用的是StreamDecoder的read方法。
public int read(char cbuf[], int offset, int length) throws IOException {
return sd.read(cbuf, offset, length);
}
StreamDecoder原理
StreamDecoder向上,对FileReader提供了读取字符到字符数组的能力。
向下,面向操作系统文件,通过字节流读取字节数据到ByteBuffer类型的bb属性中。
考虑一个事情:
当我们通过ReadableByteChannel ch读取一次数据,这时候,放入bb缓冲区,bb的大小是8192。
而StreamDecoder面向FileReader提供读取字符的能力,假如一次读取8192个字符到字符数组中。
这个时候,因为ByteBuffer bb中有8192个字节。那是不是8192个字节就能转换为8192个字符返回给FileReader呢?
答案是否定的。
字符包括中英文特殊符号等。比如一个中文UTF_8编码,通常使用3或者4个字节编码。
所以bb中的8192个字节,可能转换成3000+个字符。
这个时候bb缓冲区的数据已经解码完了。
需要继续通过ReadableByteChannel ch继续读取字节数据到bb字节缓冲区。



