将一个流的内容复制到另一个流的最佳方法是什么?有标准的实用方法吗?
当前回答
MemoryStream有.WriteTo(outstream);
. net 4.0在普通流对象上有. copyto。
net 4.0:
instream.CopyTo(outstream);
其他回答
对于。net 3.5和尝试之前:
MemoryStream1.WriteTo(MemoryStream2);
区分“CopyStream”实现的基本问题是:
读取缓冲区的大小 写入的大小 我们是否可以使用多个线程(在读取时写入)。
这些问题的答案导致了CopyStream的巨大不同的实现,这取决于您拥有的流的类型和您试图优化的内容。“最佳”实现甚至需要知道流正在读取和写入的具体硬件。
不幸的是,没有真正简单的解决办法。你可以尝试这样做:
Stream s1, s2;
byte[] buffer = new byte[4096];
int bytesRead = 0;
while (bytesRead = s1.Read(buffer, 0, buffer.Length) > 0) s2.Write(buffer, 0, bytesRead);
s1.Close(); s2.Close();
但问题是,如果没有什么可读取的,Stream类的不同实现可能会有不同的行为。从本地硬盘读取文件的流可能会阻塞,直到读操作从磁盘读取了足够的数据来填充缓冲区,并且只有在到达文件末尾时才返回较少的数据。另一方面,从网络读取的流可能返回更少的数据,即使有更多的数据需要接收。
在使用通用解决方案之前,一定要检查您正在使用的特定流类的文档。
可能有一种方法可以更有效地做到这一点,这取决于您处理的是哪种流。如果可以将一个或两个流转换为MemoryStream,则可以使用GetBuffer方法直接处理表示数据的字节数组。这让你可以使用像Array这样的方法。CopyTo,它抽象了fryguybob提出的所有问题。你可以相信. net知道复制数据的最佳方式。
我使用以下扩展方法。当一个流是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);
}
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 如何使用JSON确保字符串是有效的JSON。网
- AppSettings从.config文件中获取值
- 通过HttpClient向REST API发布一个空体
- 如何检查IEnumerable是否为空或空?
- 自动化invokerrequired代码模式
- 在c#代码中设置WPF文本框的背景颜色
- 在c#中,什么是单子?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- c#线程安全快速(est)计数器
- 如何将此foreach代码转换为Parallel.ForEach?
- 如何分裂()一个分隔字符串到一个列表<字符串>
- 如何转换列表<字符串>列表<int>?
- c#对象列表,我如何得到一个属性的和