【问题标题】:FileInputStream read byte by byte or block?FileInputStream 逐字节或逐块读取?
【发布时间】:2020-01-22 10:43:39
【问题描述】:

bufferedinputstream(BIS) 比Why is using BufferedInputStream to read a file byte by byte faster than using FileInputStream? 提供的FileInputStream(FIS) 快的原因在于

使用 BufferedInputStream,方法委托给重载的 read() 方法读取 8192 个字节并将它们缓冲直到 FIS 读取单个字节时需要它们

据我了解,磁盘是“块设备”。磁盘总是会读/写整个块,即使读取请求是针对少量数据的。 不是吗?那么,即使 FIS 和 BIS 都将如何读取完整的块而不是单个字节(如 FIS 所述)。正确的 ?那么 BIS 是如何比 FIS 快的呢?

【问题讨论】:

    标签: java file-io fileinputstream bufferedinputstream


    【解决方案1】:

    InputStream的java API就是这样。具体来说,它有这个方法:

    int read() throws IOException
    

    读取单个字节(它返回一个 int,因此它可以返回 -1 表示 EOF)。

    因此,如果您尝试从文件中读取 SINGLE BYTE,它会尝试这样做。对于像硬盘这样的块设备,它可能会读取整个块,然后丢弃除一个字节之外的所有内容,因此,如果您调用 read() 方法 8192 次,它会读取同一个块,然后结束,8192 次,每次扔掉 8191 个字节,只给你你想要的那个。因此,在整个过程中读取了 6700 万字节。哎哟。效率不高。

    鉴于内核、CPU、磁盘等都以 8192 块大小读取,BufferedInputStream(new FileInputStream)new FileInputStream 之间的性能差异为零,如果你使用了一些东西喜欢:

    byte[] buffer = new byte[8192];
    in.read(buffer);
    

    现在即使是普通的 jane unbuffered new FileInputStream 也只会从磁盘读取该块一次。

    BufferedInputStream 会在“幕后”执行此操作,即使您使用 read() 的单字节形式,然后会将来自该字节数组的数据提供给您,以便接下来 8191 次调用 read()。这就是BufferedInputStream 所做的一切。

    如果您使用read()(一次一个字节)变体(或读取的字节数组变体,但使用非常小的字节数组),那么BufferedInputStream 是有意义的。否则,它什么也做不了,也没有必要把它放在那里。

    注意:据我所知,java 不会猜测磁盘缓冲区大小是多少,只是使用一些合理的缓冲区大小。效果是一样的:如果一次使用一个字节,将文件流包装到缓冲流中可以将性能提高 1000 倍以上,如果您使用的是字节数组变体,则没有任何区别。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-27
      相关资源
      最近更新 更多