为什么要分块写入 Stream?

问题描述 投票:0回答:4

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

我对硬件有一些了解,填充缓冲区可能非常依赖于大小,并且您不想再次写入缓冲区,直到它被刷新到需要去的任何地方等等......但是使用.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 循环的所有大惊小怪(无论你决定如何构造它)?

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

c# stream point-of-interest
4个回答
20
投票

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

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

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

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


6
投票

有时,InputStream.Length 对于某些源无效,例如来自网络传输,或者缓冲区可能很大,例如从大文件中读取。国际海事组织。


2
投票

它可以保护您免受输入流长达数千兆字节的情况的影响。


2
投票

您不知道

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

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

© www.soinside.com 2019 - 2024. All rights reserved.