从一个流复制到另一个流?

时间:2011-06-02 15:06:01

标签: c# .net-2.0

对于工作,我的项目规范是使用.Net 2.0,所以我没有得到稍后带来的方便的CopyTo功能。

我需要将响应流从HttpWebResponse复制到另一个流(很可能是MemoryStream,但它可以是Stream的任何子类。我的正常策略是:

BufferedStream bufferedresponse = new BufferedStream(HttpResponse.GetResponseStream());
int count = 0;
byte[] buffer = new byte[1024];
do {
    count = bufferedresponse.Read(buffer, 0, buffer.Length);
    target.Write(buffer, 0, count);
} while (count > 0);
bufferedresponse.Close();

有更有效的方法吗?缓冲区的大小真的重要吗?在.Net 2.0中从一个流复制到另一个流的最佳方法是什么?

P.S。这是用于下载200 + MB以上的GIS tif图像。当然,可靠性至关重要。

4 个答案:

答案 0 :(得分:9)

这是一个方便的功能。是的,缓冲区大小很重要。增加它可能会在大文件上提供更好的性能。

public static void WriteTo(Stream sourceStream, Stream targetStream)
{
       byte[] buffer = new byte[0x10000];
       int n;
       while ((n = sourceStream.Read(buffer, 0, buffer.Length)) != 0)
           targetStream.Write(buffer, 0, n);
}

答案 1 :(得分:3)

缓冲区的大小很重要。例如,如果您一次一个字节地复制一兆字节的数据,那么您将通过循环进行2 ^ 20次迭代。如果你一次复制1千字节,那么你只能通过循环进行2 ^ 10次迭代。当您制作一百万个ReadWrite时,调用会产生大量开销。

对于读取FileStream,我通常使用介于64K和256K之间的缓冲区。低于32K的任何东西都表现出明显的性能下降,256K以上也是如此。使用64K缓冲区和256K缓冲区之间的区别不值得额外的内存。但请注意,这些数字在我的系统上和整个网络中。您的号码将因硬件和操作系统而异。

对于网络流,您应该选择一个与传入数据流保持同步的缓冲区大小。我建议至少4千字节,如果写入由于任何原因停止,它会给你一些缓冲。

答案 2 :(得分:1)

你可以摆脱BufferedStream,它只在您阅读流的小块时才有用。只需在变量中获取响应流并使用:

Stream response = HttpResponse.GetResponseStream();

太小的缓冲区会降低性能。您可以使用更大的缓冲区,以便至少整个IP数据包中的数据都适合。我环顾四周,4096字节就足够了。你可以使用任何大小高达85 kb的大小,之后它被分配在大对象堆中,当你没有理由时你应该避免这样做。

除此之外,它的效率和它一样高效。

答案 3 :(得分:0)

我可以想到两种方式。

  1. 检查Stream.MemberWiseClone()是否符合您的需要。它会为您提供对象的浅表副本。

  2. 如果两端都是Stream类型,请检查是否有效。

    BufferedStream bs = new BufferedStream((Stream)memoryStreamObject);