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

时间:2016-07-13 17:15:58

标签: java stream inputstream pushbackinputstream

参考stackoverflow questionInputStream可以使用mark()提供的reset()InputStream或使用PushbackInputStream来多次阅读OutOfMemoryException java.lang.Object

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

当文件大小超过内存大小时会发生什么?我认为这可能会为BossesClass hisClass = new Gson().fromJson(bossesString, BossesClass.class); 铺平道路。

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

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

1 个答案:

答案 0 :(得分:11)

这取决于流的来源。

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

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

也许类比会有所帮助。假设你的朋友正在和你说话。你不间断地仔细聆听,但是一旦完成,你就会发现你不明白他们在开始时所说的话,并且想要回顾那部分。

此时,有几种可能性。

也许你的朋友实际上正在从一本书中大声朗读。你可以简单地重新阅读这本书。

或者,也许你有远见来记录他们的独白。您可以重播录音。

然而,既然你和你的朋友都没有完美和无限的回忆,只需简单地重复十分钟前从记忆中说的就是一个选项。

InputStream就像你的朋友在说话。你们两个都没有足够的记忆力来记住,一字不漏,说什么。同样,生成数据流的过程和程序都没有足够的RAM来逐字节地存储流。为了扩展,你的程序必须依赖于它的“短期记忆”(RAM),在任何给定的时间只处理整个流的一小部分,并在遇到时“记笔记”(写入持久性存储)重点。

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

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

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

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

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