简体   繁体   English

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

[英]MemoryStream.WriteTo(Stream destinationStream) versus Stream.CopyTo(Stream destinationStream)

Which one is better : MemoryStream.WriteTo(Stream destinationStream) or Stream.CopyTo(Stream destinationStream) ?? 哪一个更好: MemoryStream.WriteTo(Stream destinationStream)Stream.CopyTo(Stream destinationStream) ??

I am talking about the comparison of these two methods without Buffer as I am doing like this : 我正在谈论没有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??
}

Update 更新

Here is what I want to Do : 这是我想要做的:

  • Open File [ Say "X" Type File] 打开文件[说“X”类型文件]
  • Parse the Contents 解析内容
  • From here I get a Bunch of new Streams [ 3 ~ 4 Files ] 从这里我得到一堆新的流[3~4个文件]
  • Parse One Stream 解析一个流
  • Extract Thousands of files [ The Stream is an Image File ] 提取成千上万的文件[流是图像文件]
  • Save the Other Streams To Files 将其他流保存到文件
  • Editing all the Files 编辑所有文件
  • Generate a New "X" Type File. 生成一个新的“X”类型文件。

I have written every bit of code which is actually working correctly.. 我写了一些实际工作正常的代码。

But Now I am optimizing the code to make the most efficient. 但是现在我正在优化代码以提高效率。

It is an historical accident that there are two ways to do the same thing. 这是一个历史性的事故,有两种方法可以做同样的事情。 MemoryStream always had the WriteTo() method, Stream didn't acquire the CopyTo() method until .NET 4. MemoryStream总是有WriteTo()方法,Stream直到.NET 4才获得CopyTo()方法。

The MemoryStream.WriteTo() version looks like this: MemoryStream.WriteTo()版本如下所示:

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

The Stream.CopyTo() implementation like this: 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() is more universal, it works for any stream. Stream.CopyTo()更通用,适用于任何流。 And helps programmers that fumble copying data from, say, a NetworkStream. 并帮助程序员摸索从NetworkStream复制数据。 Forgetting to pay attention to the return value from Read() was a very common bug. 忘记关注Read()的返回值是一个非常常见的错误。 But it of course copies the bytes twice and allocates that temporary buffer , MemoryStream doesn't need it since it can write directly from its own buffer. 但它当然会复制字节两次并分配该临时buffer ,MemoryStream不需要它,因为它可以直接从自己的缓冲区写入。 So you'd still prefer WriteTo(). 所以你仍然喜欢WriteTo()。 Noticing the difference isn't very likely. 注意到差异的可能性不大。

MemoryStream.WriteTo : Writes the entire contents of this memory stream to another stream. MemoryStream.WriteTo :将此内存流的全部内容写入另一个流。

Stream.CopyTo : Reads the bytes from the current stream and writes them to the destination stream. Stream.CopyTo :从当前流中读取字节并将它们写入目标流。 Copying begins at the current position in the current stream. 复制从当前流中的当前位置开始。 You'll need to seek back to 0, to get the whole source stream copied. 您需要回到0,才能复制整个源流。

So I think MemoryStream.WriteTo better option for this situation 所以我认为MemoryStream.WriteTo更适合这种情况

If you use Stream.CopyTo , you don't need to read all the bytes into memory to start with. 如果使用Stream.CopyTo ,则无需将所有字节读入内存即可。 However: 然而:

  • This code would be simpler if you just used File.Copy 如果你刚刚使用File.Copy这段代码会更简单
  • If you are going to load all the data into memory, you can just use: 如果要加载所有的数据到内存中,你可以使用:

     byte[] data = File.ReadAllBytes("input"); File.WriteAllBytes("output", data); 
  • You should have a using statement for the input as well as the output stream 您应该为输入和输出流using语句

If you really need processing so can't use File.Copy , using Stream.CopyTo will cope with larger files than loading everything into memory. 如果你真的需要处理所以不能使用File.Copy ,使用Stream.CopyTo将处理更大的文件而不是将所有内容加载到内存中。 You may not need that, of course, or you may need to load the whole file into memory for other reasons. 当然,您可能不需要它,或者由于其他原因您可能需要将整个文件加载到内存中。

If you have got a MemoryStream , I'd probably use MemoryStream.WriteTo rather than Stream.CopyTo , but it probably won't make much difference which you use, except that you need to make sure you're at the start of the stream when using CopyTo . 如果你一个MemoryStream ,我可能会使用MemoryStream.WriteTo而不是Stream.CopyTo ,但它可能没有太大的区别你使用, 除了你需要确保你在流的开头使用CopyTo

I think Hans Passant's claim of a bug in MemoryStream.WriteTo() is wrong; 我认为Hans Passant声称MemoryStream.WriteTo()中的错误是错误的; it does not "ignore the return value of Write()". 它不会“忽略Write()的返回值”。 Stream.Write() returns void, which implies to me that the entire count bytes are written, which implies that Stream.Write() will block as necessary to complete the operation to, eg, a NetworkStream, or throw if it ultimately fails. Stream.Write()返回void,这意味着我写入了整个计数字节,这意味着Stream.Write()将根据需要阻塞完成对NetworkStream的操作,如果最终失败则抛出。

That is indeed different from the write() system call in ?nix, and its many emulations in libc and so forth, which can return a "short write". 这确实不同于?nix中的write()系统调用,以及它在libc等中的许多仿真,它们可以返回“短写”。 I suspect Hans leaped to the conclusion that Stream.Write() followed that, which I would have expected, too, but apparently it does not. 我怀疑汉斯跳出了Stream.Write()的结论,我也曾预料到这一点,但显然它没有。

It is conceivable that Stream.Write() could perform a "short write", without returning any indication of that, requiring the caller to check that the Position property of the Stream has actually been advanced by count. 可以想象Stream.Write()可以执行“短写”,而不返回任何指示,要求调用者检查Stream的Position属性是否实际上已经按计数提前。 That would be a very error-prone API, and I doubt that it does that, but I have not thoroughly tested it. 这将是一个非常容易出错的API,我怀疑它是这样做的,但我没有彻底测试它。 (Testing it would be a bit tricky: I think you would need to hook up a TCP NetworkStream with a reader on the other end that blocked forever, and write enough to fill up the wire buffers. Or something like that...) (测试它会有点棘手:我认为你需要连接一个TCP NetworkStream,而另一端的读取器永远阻塞,写得足以填满线缓冲区。或类似的......)

The comments for Stream.Write() are not quite unambiguous: Stream.Write()的注释不是很明确:

Summary: When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. 简介:在派生类中重写时,将一个字节序列写入当前流,并使该流中的当前位置按写入的字节数前进。 Parameters: buffer: An array of bytes. 参数:buffer:一个字节数组。 This method copies count bytes from buffer to the current stream. 此方法将计数字节从缓冲区复制到当前流。

Compare that to the Linux man page for write(2): 将其与用于write(2)的Linux手册页进行比较:

write() writes up to count bytes from the buffer pointed buf to the file referred to by the file descriptor fd. write()写入从缓冲区指向buf的count个字节到文件描述符fd引用的文件。

Note the crucial "up to". 注意关键的“最多”。 That sentence is followed by explanation of some of the conditions under which a "short write" might occur, making it very explicit that it can occur. 这句话之后是对可能发生“短写”的一些条件的解释,使其明确表明它可能发生。

This is really a critical issue: we need to know how Stream.Write() behaves, beyond all doubt. 这确实是一个关键问题:我们需要知道Stream.Write()的行为,毫无疑问。

The CopyTo method creates a buffer, populates its with data from the original stream and then calls the Write method passing the created buffer as a parameter. CopyTo方法创建一个缓冲区,用原始流中的数据填充它,然后调用Write方法将创建的缓冲区作为参数传递。 The WriteTo uses the memoryStream's internal buffer to write. WriteTo使用memoryStream的内部缓冲区进行写入。 That is the difference. 这就是区别。 What is better - it is up to you to decide which method you prefer. 什么是更好的 - 由您决定您喜欢哪种方法。

Creating a MemoryStream from a HttpInputStream in Vb.Net: 从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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM