对于工作,我的项目规范是使用.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图像。当然,可靠性至关重要。
答案 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次迭代。当您制作一百万个Read
和Write
时,调用会产生大量开销。
对于读取FileStream
,我通常使用介于64K和256K之间的缓冲区。低于32K的任何东西都表现出明显的性能下降,256K以上也是如此。使用64K缓冲区和256K缓冲区之间的区别不值得额外的内存。但请注意,这些数字在我的系统上和整个网络中。您的号码将因硬件和操作系统而异。
对于网络流,您应该选择一个与传入数据流保持同步的缓冲区大小。我建议至少4千字节,如果写入由于任何原因停止,它会给你一些缓冲。
答案 2 :(得分:1)
你可以摆脱BufferedStream
,它只在您阅读流的小块时才有用。只需在变量中获取响应流并使用:
Stream response = HttpResponse.GetResponseStream();
太小的缓冲区会降低性能。您可以使用更大的缓冲区,以便至少整个IP数据包中的数据都适合。我环顾四周,4096字节就足够了。你可以使用任何大小高达85 kb的大小,之后它被分配在大对象堆中,当你没有理由时你应该避免这样做。
除此之外,它的效率和它一样高效。
答案 3 :(得分:0)
我可以想到两种方式。
检查Stream.MemberWiseClone()是否符合您的需要。它会为您提供对象的浅表副本。
如果两端都是Stream类型,请检查是否有效。
BufferedStream bs = new BufferedStream((Stream)memoryStreamObject);