将一个流的内容复制到另一个流的最佳方法是什么?有没有标准的实用方法?
从.NET 4.5开始,有Stream.CopyToAsync
方法
input.CopyToAsync(output);
这将返回一个Task
可以在完成时继续,如下所示:
await input.CopyToAsync(output) // Code from here on will be run in a continuation.
请注意,根据调用的位置,后面CopyToAsync
的代码可能会也可能不会在调用它的同一个线程上继续.
在SynchronizationContext
调用时被抓获await
将决定线程的延续将被执行的.
此外,此调用(这是一个可能会更改的实现细节)仍然会对读取和写入进行序列化(它不会浪费线程阻塞I/O完成).
从.NET 4.0开始,就是Stream.CopyTo
方法
input.CopyTo(output);
对于.NET 3.5及之前的版本
框架中没有任何东西可以帮助解决这个问题; 你必须手动复制内容,如下所示:
public static void CopyStream(Stream input, Stream output) { byte[] buffer = new byte[32768]; int read; while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { output.Write (buffer, 0, read); } }
注1:此方法允许您报告进度(到目前为止读取的x个字节...)
注2:为什么使用固定的缓冲区大小而不是input.Length
?因为该长度可能无法使用!来自文档:
如果从Stream派生的类不支持搜索,则调用Length,SetLength,Position和Seek会抛出NotSupportedException.
MemoryStream有.WriteTo(outstream);
和.NET 4.0在普通流对象上有.CopyTo.
.NET 4.0:
instream.CopyTo(outstream);
我使用以下扩展方法.当一个流是MemoryStream时,它们已经优化了重载.
public static void CopyTo(this Stream src, Stream dest) { int size = (src.CanSeek) ? Math.Min((int)(src.Length - src.Position), 0x2000) : 0x2000; byte[] buffer = new byte[size]; int n; do { n = src.Read(buffer, 0, buffer.Length); dest.Write(buffer, 0, n); } while (n != 0); } public static void CopyTo(this MemoryStream src, Stream dest) { dest.Write(src.GetBuffer(), (int)src.Position, (int)(src.Length - src.Position)); } public static void CopyTo(this Stream src, MemoryStream dest) { if (src.CanSeek) { int pos = (int)dest.Position; int length = (int)(src.Length - src.Position) + pos; dest.SetLength(length); while(pos < length) pos += src.Read(dest.GetBuffer(), pos, length - pos); } else src.CopyTo((Stream)dest); }