哪一个更好: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??
}
这是我想做的事:
我写了一些实际工作正常的代码。
但是现在我正在优化代码以提高效率。
答案 0 :(得分:16)
历史事故有两种方法可以做同样的事情。 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()。注意到差异的可能性不大。
答案 1 :(得分:6)
MemoryStream.WriteTo
:将此内存流的全部内容写入另一个流。
Stream.CopyTo
:从当前流中读取字节并将其写入目标流。复制从当前流中的当前位置开始。
您需要回到0,才能复制整个源流。
所以我认为MemoryStream.WriteTo是这种情况的更好选择
答案 2 :(得分:4)
如果使用Stream.CopyTo
,则无需将所有字节读入内存即可。但是:
File.Copy
如果 要将所有数据加载到内存中,您只需使用:
byte[] data = File.ReadAllBytes("input");
File.WriteAllBytes("output", data);
您应该输入using
语句以及输出流
如果您真的需要处理,那么无法使用File.Copy
,使用Stream.CopyTo
将处理更大的文件,而不是将所有内容加载到内存中。当然,您可能不需要它,或者由于其他原因,您可能需要将整个文件加载到内存中。
如果 得到MemoryStream
,我可能会使用MemoryStream.WriteTo
而不是Stream.CopyTo
,但它可能对您没有多大影响使用,除了,您需要确保在使用CopyTo
时确保您在流的开头。
答案 3 :(得分:1)
我认为Hans Passant声称MemoryStream.WriteTo()中的错误是错误的;它不会“忽略Write()的返回值”。 Stream.Write()返回void,这意味着我写入了整个计数字节,这意味着Stream.Write()将根据需要阻塞完成对NetworkStream的操作,如果最终失败则抛出。
这确实不同于?nix中的write()系统调用,以及libc中的许多仿真等等,可以返回“短写”。我怀疑汉斯跳出了Stream.Write()的结论,我也没想到,但显然它没有。
可以想象Stream.Write()可以执行“短写”,而不返回任何指示,要求调用者检查Stream的Position属性是否实际上已按计数提前。这将是一个非常容易出错的API,我怀疑它是这样做的,但我没有彻底测试它。 (测试它会有点棘手:我认为你需要连接一个TCP NetworkStream与另一端的读取器永远阻塞,并写入足以填充线缓冲区。或类似的东西......)< / p>
Stream.Write()的注释不是很明确:
要点: 在派生类中重写时,将一个字节序列写入当前字节 按数字流式传输并提升此流中的当前位置 写的字节数。 参数:buffer: 一个字节数组。此方法将计数字节从缓冲区复制到当前流。
将其与写入(2)的Linux手册页进行比较:
write()写入从缓冲区指向的buf计数字节到文件描述符fd引用的文件。
注意关键的“最多”。这句话之后是对可能发生“短写”的一些条件的解释,使其明确表明它可能发生。
这确实是一个关键问题:我们需要知道Stream.Write()的行为,毫无疑问。
答案 4 :(得分:0)
CopyTo方法创建一个缓冲区,用原始流中的数据填充它,然后调用Write方法将创建的缓冲区作为参数传递。 WriteTo使用memoryStream的内部缓冲区进行写入。这就是区别。什么是更好的 - 由你决定你喜欢哪种方法。
答案 5 :(得分:0)
从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)