gpt4 book ai didi

java - OutputStream 与 BufferedOutputStream

转载 作者:行者123 更新时间:2023-12-01 07:44:34 26 4
gpt4 key购买 nike

在 java 8 中,以下之间有什么真正的区别:

try (OutputStream os = Files.newOutputStream(path)) {
[...]
}

try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(path))) {
[...]
}

我读了这个SO question and answers ,但这让我很困惑。

PS:Java 11 中发生了一些变化?

最佳答案

this answer 中所述,缓冲流应该减少系统调用的数量。仅当应用程序发出大量小型读取或写入请求并导致大量系统调用时,这才有意义。这就是linked answer意思是“低效”。

通过使用一个明显更大的缓冲区,可以通过一次调用来读取或写入,并通过从缓冲区复制或复制到缓冲区来满足应用程序请求,您可以减少系统调用的数量。如果保存的系统调用比引入的复制开销更昂贵,这会提高性能。

因此,使用缓冲流并不总是更好的原因是,并非每个应用程序都发出如此小的请求。当应用程序发出合理大小的请求时,缓冲流可以做的最好的事情就是不妨碍,因此如果它有一个空缓冲区并且应用程序发出与缓冲区大小相同甚至更大的请求,则缓冲流会将请求直接传递给源流。

但是,如果应用程序的缓冲区稍微少一点,缓冲流将完成其缓冲工作,从而引入额外的复制开销。但如上所述,如果您确实节省了系统调用,并且根据架构,您可能不得不说,“……如果您实际上节省了大量的系统调用”,那么您只会获得优势。更大的缓冲区本身并不是一种改进。

一个简单的例子是,您只想将 1,000 字节写入文件,例如

byte[] data = /* something producing an array of 1,000 bytes */
try (OutputStream os = Files.newOutputStream(path)) {
os.write(data);
}

因此,如果将输出流包装在 BufferedOutputStream 中,您将获得默认大小为 8192 字节的缓冲区。由于该缓冲流不知道您总共要写入多少数据,因此它会将请求数据复制到其缓冲区(因为它较小),以便在关闭操作期间刷新(写入)。所以最终,你不会节省任何系统调用,但会产生复制开销。

因此缓冲流并不总是更高效;在某些情况下,缓冲甚至可能会降低性能。此外,有时应用程序对最高性能不感兴趣,而是对及时写入底层介质感兴趣。如果流已经是 BufferedOutputStream,则包装 OutputStream 以在需要时获得缓冲比选择退出缓冲更容易。

当您查看NIO Channel API时,在 JDK 1.4 中引入,您会注意到没有缓冲 channel 。相反,它不提供读取或写入单个字节的方法,此外,它强制程序员使用 ByteBuffer 来指导他们分离 I/O 和数据处理。这是首选方法。

关于java - OutputStream 与 BufferedOutputStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55885443/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com