C# 为什么要分块写入流?

C# 为什么要分块写入流?,c#,stream,meta,point-of-interest,C#,Stream,Meta,Point Of Interest,我想知道为什么这么多的例子将字节数组读入chuck中的流,而不是一次全部读入。。。我知道这是一个温和的问题,但我很感兴趣 我了解一些关于硬件的知识,填充缓冲区可能非常依赖于大小,在缓冲区被刷新到需要去的任何地方之前,您不会希望再次写入缓冲区。。。但对于.Net平台(和其他现代语言),我看到了这两种语言的例子。那么什么时候使用哪一个,什么时候,或者第二个是绝对不可以的 以下是我的意思(代码): 而不是: var buffer = new byte[InputStream.Length]; var

我想知道为什么这么多的例子将字节数组读入chuck中的流,而不是一次全部读入。。。我知道这是一个温和的问题,但我很感兴趣

我了解一些关于硬件的知识,填充缓冲区可能非常依赖于大小,在缓冲区被刷新到需要去的任何地方之前,您不会希望再次写入缓冲区。。。但对于.Net平台(和其他现代语言),我看到了这两种语言的例子。那么什么时候使用哪一个,什么时候,或者第二个是绝对不可以的

以下是我的意思(代码):

而不是:

var buffer = new byte[InputStream.Length];

var read = this.InputStream.Read(buffer, 0, buffer.Length);

OutputStream.Write(buffer, 0, read);
我相信两者都是合法的?那么,为什么要经历while循环的所有麻烦(无论您决定如何构建它)


我在这里扮演魔鬼代言人,因为我想尽可能多地学习:)

它可以保护您免受输入流长达数GB的情况。

您不知道读取的数据可能会返回多少。如果您正在读取一个非常大的文件,这可能会造成严重的性能问题


如果您可以控制输入,并且确保大小合理,那么您肯定可以立即读取整个数组。但是,如果用户可以提供任意输入,请特别小心。

在第一种情况下,您只需要4kB的内存。在第二种情况下,您需要与输入流数据占用的内存相同的内存。如果输入流是4GB,则需要4GB

如果文件复制操作需要4GB的RAM,您认为这会好吗?如果要准备一个20GB的磁盘映像呢

还有管道的问题。您不经常在Windows上使用它们,但在其他操作系统上也经常看到类似的情况。第二种情况等待读取所有数据,然后才将它们写入输出。但是,有时建议尽快写入数据。第一种情况下,读取输入的第一个4kB后,将立即开始写入输出流。考虑为网页提供服务:建议web服务器尽快发送数据,以便客户端的web浏览器开始呈现标题和内容的第一部分,而不是等待整个正文


但是,如果您知道输入流不会大于4kB,那么这两种情况是等效的。

有时,InputStream.Length对某些源无效,例如从网络传输,或者缓冲区可能很大,例如从一个大文件读取。在我看来,这是一个非常好的观点。。。我没有考虑过这种可能性。但是这很有意义,特别是当你靠近金属并且正在阅读接收信息的缓冲区时+1.但愿它能是+2。我想接受这个答案,因为你用一种非常简单的方式说出了一些我根本没有想到的东西。这总是很酷。但是为了SO社区的利益,最好接受对大多数人都有用的答案。一般情况下,内存中的存储量更重要,因此,如果您正在向上填充缓冲区(流)而不移动它,那就不好了。比如说,如果我们把OutputStream从等式中去掉,然后用while循环填充InputStream?因为我也看到了,这和第二个例子一样糟糕?这取决于你的具体情况,取决于你想做什么。有些算法可以处理小块数据(计算值之和,找出最大值),有些算法需要所有数据(例如:排序)。在第二种情况下,必须读取所有数据。在第一种情况下不是真的。酷。。。所以它是特定于应用的,这是我的主要想法,我认为。。。而不是大多数语言中对象本身的性质。谢谢:)你说的保护是什么意思?为什么需要它?例如,针对OutOfMemoryException.Right的保护。例如,如果您将一个文件读入内存,而该内存超出了应用程序的访问权限。鉴于但对于任何大量的数据来说,这都是可能的。因此,模式的大块度并不能保护这一点,只是将缓冲区刷新到输出流中并循环使用。@tigerswithguitars-“因此模式的大块度不能保护这一点”-当然可以。在您的示例中,您只需要配置大小(4096)的缓冲区,而不需要大小与输入流一样大的缓冲区。。。但你只会得到你想要的整个文件的一大块,对吗?所以你必须做一些实际的软件工程,确保这不会让世界崩溃(ed-app死亡)!:P
var buffer = new byte[InputStream.Length];

var read = this.InputStream.Read(buffer, 0, buffer.Length);

OutputStream.Write(buffer, 0, read);