Java中的流如何影响内存消耗?

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

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

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

InputStream 开始读取后几乎没有内存开销 。 用于打开文件的操作系统开销非常小,而在JVM中用于新对象分配的开销很小。 如果您使用默认情况下为8KB的BufferedInputStream ,也可能会产生很小的开销。

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

原因是ByteArrayOutputStream大小在达到限制后增长了2倍,并且在调用toByteArray()时它还分配了一个新的缓冲区。

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

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

第三种类型的流是一个内存流(即ByteArrayInput / Ouput),它们使用尽可能多的内存,并且会根据需要增长,并且在引用计数变为零之前不会丢弃它们的内存(它们不再使用) 。 这些流非常有用,但显然会占用大量内存。

最终的类型实际上不是流,而是一类称为读者的I / O,它提供了与流之间的数据转换的协助,如上所述。 这些流可以在raw上运行。 缓冲或内存流,将消耗与正在使用的基础流一样多的内存。