9

我已经多次使用流,但我从来没有读过太多关于它们实际上是如何工作的。除了流只是一个隐喻之外,我对它们也不太了解。一个流只代表一个字节序列。我不太了解它们实际上是如何工作的,我猜想在 Java 中打开文件流会与操作系统交互,这些操作系统具有向流提供“指针”的功能。

基本上我的问题是流如何影响内存消耗。例如,当您有一个输入流并开始从中读取时,您只会开始随着读取的字节数增加内存消耗?在 Java 中打开流时,您实际上并没有在开始阅读之前加载完整文件?如果您从一个流中读取并直接写入另一个流,您只会根据您读取的字节数(并且可能在缓冲区中)增加内存?如果你在java中读取字节到一个字节数组,那么你会随着文件的大小增加内存消耗?

听起来可能是一个奇怪的问题,但我可能需要一些指导/纠正我的理解。谢谢。

4

2 回答 2

8

上面所有的答案都是很好的答案,但我不相信他们能回答你关于内存消耗的原始问题。

在 Java 中,您可以通过多种方式查看流。首先,您有原始流,它是最低级别的流,并以最小的内存开销与底层操作系统(文件、网络等)交互。其次是缓冲流,可用于包装原始流并添加一些缓冲并显着提高性能。流缓冲为缓冲增加了固定数量的内存开销,并且可以由您的应用程序设置。不确定默认值是什么,但它可能是最小的值,例如 32K。

第三种类型的流是内存流(即 ByteArrayInput/Ouput),它们使用的内存与您写入它们的内存一样多,并且会根据需要增长,并且在引用计数变为零之前不会释放它们的内存(它们不再使用) . 这些流非常有用,但显然会消耗大量内存。

最后一种类型实际上不是流,而是一种称为 Readers 的 I/O 类,它提供与流之间的数据转换的帮助,如上所述。这些流在原始数据上运行。缓冲或内存流,并将消耗与正在使用的底层流一样多的内存。

于 2013-08-04T14:07:52.347 回答
4

从. _ _ InputStream打开文件的 OS 开销非常小,而 JVM 中的新对象分配开销很小。BufferedInputStream如果您使用默认为 8KB 的情况,也可能会有一点开销。

写入的开销很大程度上取决于您写入的位置。如果是FileOutputStream,则与上述相同。如果它是 a ByteArrayOutputStream,那么在最好的情况下它是 (2 * 流长度)字节,在最坏的情况下是(3 * 流长度) 字节。即,将 10k 字节从 an 复制InputStream到字节数组中,在最坏的情况下将分配 30k 字节。

这样做的原因是ByteArrayOutputStream在达到限制后大小增长了 2 倍,并且在您调用toByteArray().

于 2013-09-23T14:22:11.607 回答