首页 > 关于Java中使用BufferedReader读取文件的疑惑

关于Java中使用BufferedReader读取文件的疑惑

BufferedReader in = new BufferedReader(new FileReader("foo.in"));

will buffer the input from the specified file. Without buffering, each
invocation of read() or readLine() could cause bytes to be read from
the file, converted into characters, and then returned, which can be
very inefficient.

这段话怎么理解,如果使用了缓冲区就不会涉及到byte转character?
求两个读取文件的流程和效率对比,先行谢过了。


楼上的解释很好. 我做一点补充:

说到java reader缓存, 其实有两层缓存:
1. OS缓存, 把磁盘数据 读入内存, 通过read ahead, io scheduler等减少磁盘读取次数.
2. App缓存, 做缓存/预读, 即BufferredReader的角色.

BufferredReader的作用, 我的理解, 一) 减少System Call次数; 二) 减少磁盘读取次数.


我记得很久以前写过一个内部使用Byte数组的BufferedStreamReader,实测效率比原本使用Char数组的要快,不过这只是在32位系统下测试的。写这个StreamReader是为了修正文件上传组件里原本的效率问题。

实际上BufferedReader和StreamReader(例如FileReader就是一个StreamReader)的用途是不同的,流(Stream)数据就应该用byte数组以取得最大效率。而BufferedReader的作用并不是读取一堆流式数据,而是针对带有换行符的文本内容的按行读取,同时要正确处理各种字符集的文本数据。

明白BufferedReader的真正用途就很容易理解,为何内部使用Char数组,因为Java的字符和字符串都是双字节的,以解决多种字符集的问题。

BufferedReader一般创建时需要一个StreamReader的参数,由StreamReader去用流的方式读取数据。而BufferedReader只是解析流数据并组成一行一行的String。

因此,BufferedReader的Buffer也是具有非常重要的用途,按字符集解析流数据,组成Char数组,这个过程一定是需要预读取的。然后才是基于Buffer,辨析Windows和Linux不同换行符\n\r,解析出一行String返回。

用了Buffer当然还是需要从Byte到Char的转换,只不过比之不用Buffer,效率会有数量级的提高。


没有缓冲区时,每次读取操作都会导致一次文件读取操作(就是告诉操作系统内核我要读这个文件的这个部分,麻烦你帮我把它取过来)。而有缓冲区时,会一次性读取很多数据,然后按要求分次交给上层调用者。读取块大小通常是按最适合硬件的大小来读的,因为对于硬件来说,一次读取一块连续数据(比如 1K)和一次读取一个字节需要的时间几乎是一样的(都是一次读操作,只是最终提交的数据量有差异)。带缓冲的 I/O 和不带缓冲的相比效率差异是非常显著的,你可以自行写程序测试。

【热门文章】
【热门文章】