将一个流的内容复制到另一个流的最佳方法是什么?有标准的实用方法吗?


当前回答

从。net 4.5开始,就有了流。CopyToAsync方法

input.CopyToAsync(output);

这将返回一个Task,完成后可以继续执行,如下所示:

await input.CopyToAsync(output)

// Code from here on will be run in a continuation.

注意,根据对CopyToAsync调用的位置,后面的代码可能继续也可能不继续在调用它的同一个线程上。

调用await时捕获的SynchronizationContext将决定在哪个线程上执行延续。

此外,这个调用(这是一个可能会改变的实现细节)仍然对读写进行排序(它只是没有在I/O完成时浪费线程阻塞)。

从。net 4.0开始,就有了流。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异常。

其他回答

. net Framework 4引入了新的系统流类的CopyTo方法。IO命名空间。使用此方法,我们可以将一个流复制到不同流类的另一个流。

这里有一个例子。

    FileStream objFileStream = File.Open(Server.MapPath("TextFile.txt"), FileMode.Open);
    Response.Write(string.Format("FileStream Content length: {0}", objFileStream.Length.ToString()));

    MemoryStream objMemoryStream = new MemoryStream();

    // Copy File Stream to Memory Stream using CopyTo method
    objFileStream.CopyTo(objMemoryStream);
    Response.Write("<br/><br/>");
    Response.Write(string.Format("MemoryStream Content length: {0}", objMemoryStream.Length.ToString()));
    Response.Write("<br/><br/>");

MemoryStream有.WriteTo(outstream);

. net 4.0在普通流对象上有. copyto。

net 4.0:

instream.CopyTo(outstream);

对于。net 3.5和尝试之前:

MemoryStream1.WriteTo(MemoryStream2);

下面的代码可以解决这个问题,使用CopyTo将流复制到MemoryStream

Stream stream = new MemoryStream();

//任何需要输入流的函数。在我的情况下,保存PDF文件为流 document.Save(流);

MemoryStream newMs = (MemoryStream)stream;

byte[] getByte = newMs.ToArray();

//注意-请在finally块中处理流,而不是在using块中处理,因为它会抛出一个错误'访问被拒绝,因为流被关闭'

从。net 4.5开始,就有了流。CopyToAsync方法

input.CopyToAsync(output);

这将返回一个Task,完成后可以继续执行,如下所示:

await input.CopyToAsync(output)

// Code from here on will be run in a continuation.

注意,根据对CopyToAsync调用的位置,后面的代码可能继续也可能不继续在调用它的同一个线程上。

调用await时捕获的SynchronizationContext将决定在哪个线程上执行延续。

此外,这个调用(这是一个可能会改变的实现细节)仍然对读写进行排序(它只是没有在I/O完成时浪费线程阻塞)。

从。net 4.0开始,就有了流。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异常。