Java Docs说Java Docs
公共类BufferedReader 扩展阅读器
从字符输入流中读取文本,缓冲字符,以便提供>高效读取字符,数组和行。
可以指定缓冲区大小,也可以使用默认大小。默认值很大>足以满足大多数用途。
通常,由读取器构成的每个读取请求使得相应的读取请求>由基础字符或字节流构成。因此,建议在其read()操作可能成本较高的任何Reader周围包装一个> BufferedReader,例如> FileReaders和InputStreamReaders。例如,
BufferedReader in = new BufferedReader(new FileReader(“foo.in”));
将缓冲指定文件的输入。如果没有缓冲,每次调用> read()或readLine()都可能导致从文件中读取字节,转换为>字符,然后返回,这可能效率非常低。
但是通过挂钩Filereader,我们使用FileReader的read方法来读取一次读取一个字符的文件,所以如果我的文件包含2000个字符,FileReader首先会一次读取一个2000个字符并将其传输到缓冲区,我们会读取来自缓冲区使用bufferedreader那么它如何增强性能。我们只能使用FileReader吗?
答案 0 :(得分:2)
你可以想象它:
您位于A
位置,而您的数据位于B
位置A
和B
彼此相距5公里。
通过一次一个单位撤消数据,你必须每次从A
到B
进行旅行(读取基础字符或字节流的请求),因此如果你有100个数据单位,你将要做100次旅行,这是花费时间。
Wehen Buffering你就像拥有一辆卡车,当你做旅行时,你需要将一些数据单元(缓冲区的大小)加载到你的载货地板(缓冲区)上,这样你就不必去旅行了。很多次,因此效率很高。
通常在打开文件进行阅读时,您想要阅读更多的字符,因此首选BufferedRead。
这同样适用于写作。
修改强>
首先,FileReader
不读取自身,它是底层输入流。在这种情况下FileInputStream
。
BufferedReader
为您管理FileReasder
,并在其fill()
方法中使用方法
abstract public int read(char cbuf[], int off, int len) throws IOException;
你的Reader
填补了缓冲区。 它不使用只读取单个字符的方法!换句话说,当填充方法必须执行 travel 时,它会从底层检索一系列字符输入流并将其保存在内存中,这样当您需要读取时,它首先在缓冲区中查找,使用它并在必要时重新填充它。
你可以通过自己调用read(char cbuf[], int off, int len)
FileReader
来实现同样的目标,但是你所拥有的只是一系列具有例如以下文字的字符
Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore et dolore
magna aliquyam erat, sed diam voluptua.
例如,可能看起来像这样
"onsetetur sadipscing elitr,\r\nsed diam nonumy eirmod temp"
如果需要,你必须处理它才能找到一行文字。
但是你没有必要因为BufferedReader
为你照顾这个,这就是为什么你最好写的原因之一
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
答案 1 :(得分:2)
BufferedReader是使用缓冲区的常见示例。
让我们分解BufferedReader(J7u51)的read()方法:
ensureOpen();
for (;;) {
if (nextChar >= nChars) {
fill();
if (nextChar >= nChars)
return -1;
}
当且仅当我们要求的字符超过以前的一些调用时才会调用fill()方法(调用底层读者)。
if (skipLF) {
skipLF = false;
if (cb[nextChar] == '\n') {
nextChar++;
continue;
}
}
return cb[nextChar++];
}
这里我们只返回适当的值。
所以BufferedReader总是“在你想要更多的时候阅读更多内容”然后,如果你真的想要更多,那么可以给你“更有效”。
看一下这个例子:
YourApp BufferedReader (bufferSize=10) FileReader
read(1 character) ->
buffer empty, load 10 characters -> disk latency 10 ms
<- return 10 characters
buffer filled with 10 characters
<- return 1 character, 9 remaining
in buffer
read(1 character) ->
<- return 1 character, 8 remaining
in buffer
.
.
.
read(1 character) ->
<- return 1 character, 0 remaining
in buffer
循环的总执行时间是10毫秒+无关紧要的Java开销。
现在,将它与无缓冲版本进行比较:
YourApp FileReader
read(1 character) ->
disk latency 10 ms
<- return 1 character
read(1 character) ->
disk latency 10 ms
<- return 1 character
.
.
.
read(1 character) ->
disk latency 10 ms
<- return 1 character
HDD调用导致的开销远大于前一种情况。
答案 2 :(得分:1)
首先,BufferedReader
不会一次完全读取已包装的Reader
。相反,如果需要,它会读取特定大小的块(默认为8192个字符)。
其次,使用BufferedReader
而不是直接使用FileReader
的原因是访问文件比访问内存中的对象要复杂得多。因此,如果您逐行读取文件,则每行访问一次文件系统。使用BufferedReader
,可以减少读取操作的数量,从而提高代码的性能。
答案 3 :(得分:1)
谁说FileReader
个实例将用于一次读取一个字符?
您问题的最佳解决方案是直接转到BufferedReader
的源代码。如果您对此进行调查,您会在内部看到BufferedReader
将调用已包装read(char[],int,int)
的{{1}}方法(或其所包含的FileReader
)。
Here您拥有Reader
read
方法的代码。对BufferedReader
包裹Reader
的实际调用是在fill
方法中执行的。我认为值得检查一下。