当前位置: 首页 > 知识库问答 >
问题:

BufferedReader读取的字节数

易元青
2023-03-14

据我所知,缓冲阅读器比非缓冲阅读器优化了很多,因为每次读取都将从内存中完成,不需要每次都从磁盘/网络进行I/O读/写。

所以我在这里阅读答案:

缓冲读取器和文件读取器之间的特定区别

我被第二个答案弄糊涂了,这个答案似乎有很高的票数:

当向BufferedReader对象发出“read”指令时,它会使用FileReader对象从文件中读取数据。当给出指令时,FileReader对象一次读取2(或4)个字节并将数据返回给BufferedReader,读取器会一直这样做,直到遇到“\n”或“\r\n”(行尾符号)。一旦缓冲了一行,读取器会耐心等待,直到给出缓冲下一行的指令。

对吗?我认为我们已经完全忘记了缓冲区读取器的概念,如果缓冲区需要读取多个2字节,那么我可以使用文件读取器,也可以使用它。缓冲读取器的思想是,它应该一次读取大数据块,因此I/O访问的数量将远远少于文件读取器。

如果我错了,有人能纠正我吗?

共有3个答案

阎晗日
2023-03-14

让我们用Linux中的一个小的UTF-8编码文件做一个实验,然后创建它的hexump,并尝试理解发生了什么:

$ echo "Try my delicious pork-chop ribs!" > ribs.txt
$ cat ribs.txt | xxd -g 1 > ribs.hexdump`
$ cat ribs.hexdump 
00000000: 54 72 79 20 6d 79 20 64 65 6c 69 63 69 6f 75 73  Try my delichtml" target="_blank">ious
00000010: 20 70 6f 72 6b 2d 63 68 6f 70 20 72 69 62 73 21   pork-chop ribs!
00000020: 0a    
                                       .

现在,使用jshell,并为FileReader、BufferedReader和StringBuilder对象创建实例:

    jshell> FileReader afr = new FileReader("/path/to/file/ribs.txt/")
    afr ==> java.io.FileReader@3d012ddd
'    
    jshell> BufferedReader bfr = new BufferedReader(afr)
    bfr ==> java.io.BufferedReader@6504e3b2
    
    jshell> StringBuilder ct = new StringBuilder()
    ct ==> 

`“ct”是StringBuilder对象的内容。现在是空的。因此,让我们构造一个每次迭代8次的for循环,看看它做了什么:

for (int i=0; i < 7; i++) {
if ((value = bfr.read()) != -1) { ct.append((char) value); }
i++;
}

在jshell中,我们这样做:'

    jshell> int value;
    value ==> 0
    
    jshell> for (int i=0; i < 7; i++) {
       ...> if ((value = bfr.read()) != -1) { ct.append((char) value); }
       ...> i++;
       ...> }
`

让我们看一下内容:'

jshell> ct
ct ==> Try 

' 我们可以查看我们之前准备的十六进制转储文件,以尝试了解我们所处的位置:

`
    00000000: 54 72 79 20 6d 79 20 64 65 6c 69 63 69 6f 75 73  Try my delicious
              T  r  y  SP (<---- YOU ARE HERE)
`

让我们用另一个迭代周期来确认这一点:

`     
    jshell> for (int i=0; i < 7; i++) {
       ...> if ((value = bfr.read()) != -1) { ct.append((char) value); }
       ...> i++;
       ...> }
    
    jshell> ct
    ct ==> Try my d
    
    00000000: 54 72 79 20 6d 79 20 64 65 6c 69 63 69 6f 75 73  Try my delicious
              T  r  y  SP m  y  SP d (<---- YOU ARE HERE)
`

看:你要求8个字符,它却给了你4个字符(每个2字节)!FileReader确实一次读取2个字节!汉克

夏建木
2023-03-14

他的观点是FileInputStream一次读取N个字节,对它读取的数据不感兴趣。BufferedReader最终使用FileInputStream(读取文件时)并执行重复读取部分,但它确实对读取的字节感兴趣,将它们视为字符数据(编码考虑等)并将它们分成行

当然,你可以自己写,不用BufferedReader,但你可以对计算领域的任何东西说同样的话:“我不喜欢NVidia的显示驱动程序,所以我坐下来花了3年时间写自己的。现在我正在启动一个新的操作系统。当量子计算机成为主流时,就完蛋了”——几乎没有人这样做;这被称为重新发明轮子,我们不这样做是有原因的:在大多数情况下,其他人发明的轮子对我们来说已经很好了/比我们自己有时间做的更好

注意;您似乎对缓冲读取器最终一次从数据源读取一两个字节的断言有异议。可能没有,但我不认为这是这个家伙要表达的观点(帖子中使用的语言相当模糊)。无论它如何从输入流/读取器读取字节,缓冲读取器肯定会在查找换行符时逐个字符地检查它读取的数据,因此它可以使ReadLine()工作。它将独立于用于读取文件的策略执行此操作(也许它会重复读取4096字节块,但它肯定必须在解释数据时逐字节处理数据)

最终考虑文件访问是缓存的,并且读取的合并可能发生在许多级别:调用 ReaderX.Read() 几乎肯定不会导致硬盘停止它正在执行的所有操作,转到某个扇区,读取单个字节,然后返回到之前执行的操作。因此,您可能会对 Read() 一个字符发出一百万次调用,这些字符不会比将 Read() 调用一次到兆字节缓冲区中那样多导致硬盘抖动

彭骏
2023-03-14

看看< code > buffered reader javadoc:

因此,它会预先从底层资源中缓冲数据,随后的read指令使用缓冲区来提高效率。

 类似资料:
  • 对不起,如果这个问题是一个迟钝的,但我没有得到一个答案,我正在寻找。 Java docs这样说 通常,对读取器的每个读取请求都会导致对底层字符或字节流的相应读取请求。因此,建议将BufferedReader包装在任何读取()操作可能代价高昂的读取器周围,例如FileReaders>和InputStreamReaders。例如, 将缓冲来自指定文件的输入。如果不进行缓冲,每次调用read()或rea

  • 编辑:到目前为止,我所见过的每一个类似LineReader的类似乎都被缓冲了。有没有人知道一个无缓冲的类linereader类?

  • 如果文件很小,我就工作。但是,当文件变大时,偏移量将小于实际值。我怎样才能得到抵消?

  • 问题内容: 我正在阅读文件,但我不知道如何阅读口音和特殊字符,这是我阅读的代码,我必须添加其他编纂,但我不知道该怎么做 谢谢 问题答案: 请尝试以下操作:

  • 如何使用将所有可用字符读入? 编辑 1。委托不关心字符串有多长,它只需要处理通过套接字到达的任何哈达-以及它的全部内容 2。我不需要将数据切成块--我希望读取到达 3的每一个信息。是的,我有一个无限循环,因为我需要保持与套接字的连接并监听数据,直到客户端删除连接-当我获得时。我为套接字使用单独的线程,因为会有更多的套接字要听。

  • 我有一个名为“add”的方法,它将字符串作为参数,并使用bufferedwriter将其写入文件。完成此操作后,bufferedwriter将被刷新。 在另一个方法“read”中,我遍历文件中的行,但这些行是空的(因此我不能打印它们)。