MemoryStream.WriteTo(Stream destinationStream)与Stream.CopyTo(Stream destinationStream)

哪一个更好: MemoryStream.WriteTo(Stream destinationStream)Stream.CopyTo(Stream destinationStream) ??

我正在谈论没有Buffer的这两种方法的比较,因为我这样做:

 Stream str = File.Open("SomeFile.file"); MemoryStream mstr = new MemoryStream(File.ReadAllBytes("SomeFile.file")); using(var Ms = File.Create("NewFile.file", 8 * 1024)) { str.CopyTo(Ms) or mstr.WriteTo(Ms);// Which one will be better?? } 

更新

这是我想要做的:

  • 打开文件[说“X”类型文件]
  • 解析内容
  • 从这里我得到一堆新的流[3~4个文件]
  • 解析一个流
  • 提取成千上万的文件[流是图像文件]
  • 将其他流保存到文件
  • 编辑所有文件
  • 生成新的“X”类型文件。

我写了一些实际工作正常的代码。

但是现在我正在优化代码以提高效率。

这是一个历史事故,有两种方法可以做同样的事情。 MemoryStream总是有WriteTo()方法,Stream直到.NET 4才获得CopyTo()方法。

MemoryStream.WriteTo()版本如下所示:

 public virtual void WriteTo(Stream stream) { // Exception throwing code elided... stream.Write(this._buffer, this._origin, this._length - this._origin); } 

Stream.CopyTo()实现如下:

 private void InternalCopyTo(Stream destination, int bufferSize) { int num; byte[] buffer = new byte[bufferSize]; while ((num = this.Read(buffer, 0, buffer.Length)) != 0) { destination.Write(buffer, 0, num); } } 

Stream.CopyTo()更通用,适用于任何流。 并帮助程序员摸索复制数据,例如NetworkStream。 忘记关注Read()的返回值是一个非常常见的错误。 但它当然会复制字节两次并分配该临时buffer ,MemoryStream不需要它,因为它可以直接从自己的缓冲区写入。 所以你仍然喜欢WriteTo()。 注意到差异的可能性不大。

MemoryStream.WriteTo :将此内存流的全部内容写入另一个流。

Stream.CopyTo :从当前流中读取字节并将它们写入目标流。 复制从当前流中的当前位置开始。 您需要回到0,才能复制整个源流。

所以我认为MemoryStream.WriteTo更适合这种情况

如果使用Stream.CopyTo ,则无需将所有字节读入内存即可。 然而:

  • 如果你刚刚使用File.Copy这段代码会更简单
  • 如果要将所有数据加载到内存中,可以使用:

     byte[] data = File.ReadAllBytes("input"); File.WriteAllBytes("output", data); 
  • 您应该为输入和输出流using语句

如果你真的需要处理所以不能使用File.Copy ,使用Stream.CopyTo将处理更大的文件,而不是将所有内容加载到内存中。 当然,您可能不需要它,或者由于其他原因您可能需要将整个文件加载到内存中。

如果你一个MemoryStream ,我可能会使用MemoryStream.WriteTo而不是Stream.CopyTo ,但它可能没有太大的区别你使用, 除了你需要确保你在流的开头使用CopyTo

我认为Hans Passant声称MemoryStream.WriteTo()中的错误是错误的; 它不会“忽略Write()的返回值”。 Stream.Write()返回void,这意味着我写入了整个计数字节,这意味着Stream.Write()将根据需要阻塞完成对NetworkStream的操作,如果最终失败则抛出。

这确实不同于?nix中的write()系统调用,以及它在libc等中的许多仿真,它们可以返回“短写”。 我怀疑汉斯跳出了Stream.Write()的结论,我也曾预料到这一点,但显然它没有。

可以想象Stream.Write()可以执行“短写”,而不返回任何指示,要求调用者检查Stream的Position属性是否实际上已按计数提前。 这将是一个非常容易出错的API,我怀疑它是如此,但我还没有彻底测试它。 (测试它会有点棘手:我认为你需要连接一个TCP NetworkStream与另一端的读取器永远阻塞,并写入足以填充线缓冲区。或类似的东西…)

Stream.Write()的注释不是很明确:

简介:在派生类中重写时,将一个字节序列写入当前流,并使该流中的当前位置按写入的字节数前进。 参数:buffer:一个字节数组。 此方法将计数字节从缓冲区复制到当前流。

将其与用于write(2)的Linux手册页进行比较:

write()写入从缓冲区指向buf的count个字节到文件描述符fd引用的文件。

注意关键的“最多”。 这句话之后是对可能发生“短写”的一些条件的解释,使其明确表明它可能发生。

这确实是一个关键问题:我们需要知道Stream.Write()的行为,毫无疑问。

CopyTo方法创建一个缓冲区,用原始流中的数据填充它,然后调用Write方法将创建的缓冲区作为参数传递。 WriteTo使用memoryStream的内部缓冲区进行写入。 这就是区别。 什么是更好的 – 由您决定您喜欢哪种方法。

从Vb.Net中的HttpInputStream创建MemoryStream:

 Dim filename As String = MyFile.PostedFile.FileName Dim fileData As Byte() = Nothing Using binaryReader = New BinaryReader(MyFile.PostedFile.InputStream) binaryReader.BaseStream.Position = 0 fileData = binaryReader.ReadBytes(MyFile.PostedFile.ContentLength) End Using Dim memoryStream As MemoryStream = New MemoryStream(fileData)