BufferedReader中的缓冲区大小是多少?

28
构造函数中缓冲区大小的意义是什么?
BufferedReader(Reader in, int size)

我已经编写了这个程序:

import java.io.*;
class bufferedReaderEx{
    public static void main(String args[]){
        InputStreamReader isr = null;
        BufferedReader br = null;
            try{
                isr = new InputStreamReader(System.in);
//              System.out.println("Write data: ");
//              int i = isr.read();
//              System.out.println("Data read is: " + i);
                //Thus the InputStreamReader is useful for reading the character from the stream
                System.out.println("Enter the data to be read by the bufferedReader: ");
                //here isr is containing the lnefeed already so this is needed to be flushed.
                br = new BufferedReader(isr, 2);
                String str = br.readLine();
                System.out.println("The data is : :" +  str);
            }catch(IOException e){
                System.out.println("Can't read: " + e.getMessage());
            }
    }
}

输出:

Enter the data to be read by the bufferedReader: Hello world and hello world again
The data is: Hello world and hello world again

那么缓冲大小是什么意思呢?我本来想让它只阅读两个字符,但实际上并不是这样的。

3个回答

38

BufferedReader 缓冲输入,正如其名称所示。这意味着它在将输入传递给你之前,会将其从输入源读入缓冲区中。这里的缓冲区大小是指它缓冲的字节数。

从大多数来源读取输入都非常慢。仅有 2 字节的缓冲区会影响性能,因为你的程序很可能会大部分时间等待输入。使用缓冲区大小为 2,读取 100 字节将导致从内存中的缓冲区中读取 2 字节(非常快),填充缓冲区(非常慢),从缓冲区中读取 2 字节(非常快),再次填充缓冲区(非常慢),以此类推 - 整体速度非常慢。使用缓冲区大小为 100,则读取 100 字节将导致从内存中的缓冲区中读取 100 字节(非常快)- 整体速度非常快。这假设在读取时缓冲区包含了这 100 字节,在你的情况下,这是一个合理的假设。

除非你知道自己在做什么,否则应该使用默认的缓冲区大小,它相当大。使用较小的缓冲区的一个原因是运行在内存受限设备上,因为缓冲区会消耗内存。


那么缓冲区大小的意义是什么?你能解释一下吗? - codeomnitrix
1
@codeonnitrix 添加了一些解释。如果这已经足够,请告诉我。 - moinudin
大小不是缓冲区中字符的数量而不是字节吗? - AndrewBourgeois
Logcat显示:BufferedReader构造函数中使用了默认缓冲区大小。如果需要8k字符缓冲区,最好明确指定。什么是正确的方法? - J Webb
使用FileInputStream,缓冲区大小是否直接影响从该文件读取的系统调用次数?例如totalFileSize / bufferSize = 系统调用次数?因此,如果您按行读取大型文件,则将缓冲区大小设置为较高值可能是有意义的,以便减少系统调用。只是思考,我无法从源代码中判断,你认为呢? - lisak
所以,根据你的说法,如果我总是根据文件大小定义缓冲区的大小,比如 byte[] buffer = new byte[inputstream.available()],那么这将是最快的,对吗?但是,我们经常看到的是使用默认大小、2048或1024的缓冲区,而不是找到实现这种方式的人。 - WesternGun

14

http://www.docjar.com/html/api/java/io/BufferedReader.java.html

根据Java文档,缺省缓冲区大小为8192个字符容量。行大小被视为80个字符容量。
8192的缓冲区大小对于较小的文件大小已经足够。但是,如果文件包含超过8192个字符,则缓冲读取器的fill方法将在从文件读取内容之前增加缓冲区大小。对于更大的内容文件,最好在创建缓冲读取器时通过构造函数设置自己的最大缓冲区大小,以避免重新创建内存并将旧数组复制到新创建的数组中。

直截了当、清晰明了的信息。谢谢@user1923551 - With A SpiRIT
5
这个缓冲区实际上永远不会增长,它的大小是恒定的。它仅用作读取文件时的中间内存存储器。我懒得解释更多了,所以看这个链接:https://dev59.com/IHRB5IYBdhLWcg3wXWK2 - gargii
@gargii 给链接点赞,但在Java BufferedReader中,缓冲区大小可以在构造函数中配置,例如 new BufferedReader(Reader, size),这样您就可以决定缓冲区的大小了,不是吗?虽然默认大小8192通常足够并且适合。 - WesternGun

11

当您读取或写入文件时,必须访问内核,以实际获得对该文件的访问权限。所有文件操作都必须经过内核。这是一个相当昂贵的操作。缓冲导致一块字节被读取;这些字节被保存在RAM的临时位置,并从该位置中读取字节。通过这种方式,您不会频繁请求内核执行文件IO。

如果您使用巨大的缓冲区大小,将会不必要地占用RAM。如果您使用小型缓冲区,则会不断向内核请求文件。最好允许使用默认值。您可以指定缓冲区大小并进行实验。大多数计算机将一次读取一个扇区或整数个扇区。扇区大小取决于计算机的格式化方式。

以下实验很有趣。创建一个包含1,000,000个零的文件。使用操作系统的计时功能查看它将其复制到另一个文件的速度(您将编写支持缓冲和非缓冲IO的复制程序)。使用各种缓冲区大小进行计时,包括默认值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接