在不将其存储在内存中的情况下两次读取输入流

9 浏览
0 Comments

在不将其存储在内存中的情况下两次读取输入流

根据stackoverflow问题所说,可以使用mark()reset()方法提供的InputStream或使用PushbackInputStream来多次读取InputStream。在所有这些情况下,流的内容被存储在字节数组中(即文件的原始内容存储在主内存中),并且可以多次重用。

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

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

请帮我解决这个问题。提前感谢您的帮助。

0
0 Comments

读取输入流两次而不将其存储在内存中的问题可能出现的原因是,如果流的来源是本地文件,可以重新打开和重新读取流,如果流是由进程、远程服务等动态生成的,则可能无法重新生成它。在这种情况下,需要将其存储在内存或一些更持久(但较慢)的存储介质中,如文件系统或存储服务。

解决方法是将流复制到某个持久存储中,这就像录制朋友的演讲一样,可以随时重放。另一种解决方法是使用支持多次读取的数据源,或者在检索数据时将其存储起来,以便能够第二次提供数据。

在网络上传输数据时,如果接收方无法立即响应输入,TCP和许多其他协议会分配一个小缓冲区来存储发送方的一些数据。但是,它们也有一种告诉发送方等待的方法,即发送数据太快-流量控制。这就像告诉朋友暂停一下,让你赶上记笔记。

在浏览器上传文件的场景中,如果服务器忙碌,无法立即读取该流,那么在这段延迟期间数据存储在哪里?当服务器无法跟上时,浏览器将被指示暂停上传,直到缓冲区中有更多空间为止。上传速度取决于浏览器从磁盘读取文件的速度,网络链接的速度和服务器处理上传数据的速度。即使网络和客户端很快,也会受到这个链条中最弱环节的限制。

对于从远程服务接收到的数据,如果文件在我们的机器上,我们可以将流视为传输数据的管道。但是,对于通过网络传输的数据,流是打开的,用于从远程服务的浏览器中读取数据。流打开的位置(即,用于读取的流包含文件引用点)告诉流从何处读取文件。为什么流不能再次从相同的引用点读取数据,因为它保存了引用呢?这个问题的答案是,流只是连接数据源和数据消费者的短管道,并不默认存储任何内容。要读取数据两次,必须使用提供两次数据的源,或者在检索数据时存储数据以便能够第二次提供数据。

在这种情况下,InputStream由TCP上的HTTP实现。这两个底层协议都不支持“重放”数据流。浏览器打开与服务器的TCP连接,发送适当的HTTP头来描述传输,发送数据,然后关闭TCP套接字。服务器不再与浏览器有任何连接来请求重放,并且HTTP也不支持服务器到客户端的请求。

当使用像HttpServletRequest这样的API多次读取标头时,实现会从浏览器读取流的一部分,并将重要的信息(如标头名称和值)存储在RAM中,以便可以多次读取。但它不会存储流中的所有内容,比如标记之间的空格。如果客户端发送了太多的标头,实现最终会失败,因为它假设只有少量标头数据,而正文可以无限长。

最后一个问题不太清楚,但我猜测你的意思并更新了我的答案。在网络传输过程中,如果服务器尚未准备好读取流,数据会存储在流实例中,直到服务器读取数据为止。数据会在网络协议的不同层次上进行存储,具体取决于底层协议的实现方式。

0