两次读取输入流而不将其存储在内存中

Reading an input stream twice without storing it in memory

参考Whosebug question据说InputStream可以用InputStream提供的mark()reset()多次读取或者通过使用 PushbackInputStream.

在所有这些情况下,流的内容存储在字节数组中(即文件的原始内容存储在主内存中)并多次重复使用。

当文件大小超过内存大小时会发生什么?我认为这可能为 OutOfMemoryException.

铺平道路

有没有更好的方法可以多次读取流内容而不将流内容存储在本地(即;在主内存中)?

请帮助我了解这一点。提前致谢。

这取决于流的来源。

如果是本地文件,您可以根据需要多次重新打开和读取流。

如果它是由进程、远程服务等动态生成的,您可能无法自由地重新生成它。在这种情况下,您需要将其存储在内存中或一些更持久(且速度较慢)的存储中,例如文件系统或存储服务。


也许打个比方会有所帮助。假设你的朋友正在和你长谈。你不间断地仔细听,但当他们听完后,你意识到你在开头部分没有听懂,想复习那部分。

在这一点上,有几种可能性。

也许您的朋友实际上是在大声朗读一本书。你可以简单地重读这本书。

或者,也许你不得不先见之明来记录他们的独白。您可以重放录音。

但是,由于您和您的朋友都没有完美和无限的回忆,仅凭记忆逐字重复十分钟前所说的话不是一个选择。

一个InputStream就像你的朋友在说话。你们俩的记忆力都不够好,无法逐字逐句地记住所说的内容。同样,生成数据流的进程和您的程序都没有足够的 RAM 来逐字节地存储流。要扩展,您的程序必须依赖其 "short-term memory"(RAM),在任何给定时间只处理整个流的一小部分,并且在遇到时 "taking notes"(写入持久存储)要点。

如果流的来源是本地文件,那就像你的朋友在看书。你们中的任何一个都可以轻松地重新阅读该内容。

如果您将流复制到某个持久存储,就像录制您朋友的演讲一样。您可以随时重播。


考虑这样一种情况,浏览器正在上传一个大文件,但服务器很忙,有一段时间无法读取该流。在该延迟期间,数据存储在哪里?

因为接收方不能总是立即响应输入,TCP 和许多其他协议分配一个小缓冲区来存储来自发送方的一些数据。但是,他们也有办法告诉发送方等待,他们发送数据的速度太快了——流量控制。回到这个类比,这就像告诉你的朋友在你记笔记的时候暂停一下。

当浏览器上传文件时,首先,缓冲区会被填满。但如果服务器跟不上,浏览器将被指示暂停上传,直到缓冲区中有更多空间。 (这通常发生在 OS 和 TCP 级别;客户端和服务器应用程序不直接管理它。)上传速度取决于浏览器从磁盘读取文件的速度、网络速度 link是,服务器处理上传数据的速度。即使是快速的网络和客户端也会受到此链中弱 link 的限制。