为啥要分块写入 Stream?
Posted
技术标签:
【中文标题】为啥要分块写入 Stream?【英文标题】:Why write to Stream in chunks?为什么要分块写入 Stream? 【发布时间】:2012-11-16 10:23:23 【问题描述】:我想知道为什么这么多示例将字节数组读入流中而不是一次全部...我知道这是一个软问题,但我很感兴趣。
我了解一些关于硬件和填充缓冲区的信息可能非常依赖于大小,并且您不想再次写入缓冲区,直到它被刷新到它需要去的任何地方等等......但是使用 .Net 平台(和其他现代语言)我看到了两者的例子。那么什么时候用哪个,什么时候用,或者说第二个绝对不行?
这是我的意思的东西(代码):
var buffer = new byte[4096];
while (true)
var read = this.InputStream.Read(buffer, 0, buffer.Length);
if (read == 0)
break;
OutputStream.Write(buffer, 0, read);
而不是:
var buffer = new byte[InputStream.Length];
var read = this.InputStream.Read(buffer, 0, buffer.Length);
OutputStream.Write(buffer, 0, read);
我相信两者都是合法的?那么,为什么要经历所有的 while 循环(无论你决定如何构建它)?
我在这里扮演魔鬼代言人,因为我想尽可能多地学习:)
【问题讨论】:
【参考方案1】:在第一种情况下,您只需要 4kB 的内存。在第二种情况下,您需要与输入流数据一样多的内存。如果输入流为 4GB,则需要 4GB。
您认为如果文件复制操作需要 4GB 的 RAM 会更好吗?如果您要准备一个 20GB 的磁盘映像怎么办?
管道也有这个东西。您不经常在 Windows 上使用它们,但在其他操作系统上经常会看到类似的情况。第二种情况等待所有数据被读取,然后才将它们写入输出。但是,有时建议尽快写入数据——第一种情况将在读取前 4kB 输入后立即开始写入输出流。考虑为网页提供服务:建议网络服务器尽快发送数据,以便客户端的网络浏览器开始呈现标题和内容的第一部分,而不是等待整个正文。
但是,如果您知道输入流不会大于 4kB,那么这两种情况是等价的。
【讨论】:
一般情况下,您在内存中保存的数量更重要,因此如果您正在填充缓冲区(流)而不移动它,那就不好了。假设我们是否将 OutputStream 排除在等式之外,而只是用 while 循环填充 InputStream?因为我也看到了这个,那会和第二个例子一样糟糕吗? 这完全取决于您的具体情况,取决于您想做什么。有些算法可以对小块进行操作(计算值的总和,找出最大值),有些算法需要所有数据(例如:排序)。在第二种情况下,需要读取所有数据。在第一种情况下——不是真的。 酷......所以它是特定于应用程序的,我认为这是我的主要想法......而不是大多数语言中对象本身的性质。谢谢:)【参考方案2】:有时,InputStream.Length 对某些源无效,例如来自网络传输,或者缓冲区可能很大,例如从大文件中读取。国际海事组织。
【讨论】:
这是一个非常好的观点......我没有想过这种可能性。但这很有意义,尤其是当您靠近金属并阅读缓冲区接收信息时! +1 ...希望它可以是+2。我想接受这个答案,因为您以一种非常简单的方式提出了我根本没想到的东西。这总是很酷。但为了 SO 社区的利益,最好接受对大多数人有用的答案。【参考方案3】:它可以保护您免受输入流长达数 GB 的情况。
【讨论】:
保护是什么意思?为什么需要它? 针对例如 OutOfMemoryException 的保护。 对。例如,如果您将文件读取到超出应用程序访问权限的内存中。给定。但这对于任何大量数据都是可能的。因此,模式的块度并不能保护这一点,只是将缓冲区刷新到输出流中并回收。 @tigerswithguitars - “所以模式的厚实并不能保护这一点” - 确实如此。在您的示例中,您只需要一个配置大小 (4096) 的缓冲区,而不是一个大小与输入流一样大的缓冲区。 很酷,我明白了......但你只会拥有你想要的整个文件的一部分,对吗?所以你必须做一些实际的软件工程,并确保这不会让世界崩溃(ed - app die)! :P【参考方案4】:您不知道Read
可能会返回多少数据。如果您正在读取一个非常大的文件,这可能会造成严重的性能问题。
如果您可以控制输入,并且确定大小合理,那么您当然可以一次读取整个数组。但如果用户可以提供任意输入,则要特别小心。
【讨论】:
以上是关于为啥要分块写入 Stream?的主要内容,如果未能解决你的问题,请参考以下文章