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


当前回答

不幸的是,没有真正简单的解决办法。你可以尝试这样做:

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类的不同实现可能会有不同的行为。从本地硬盘读取文件的流可能会阻塞,直到读操作从磁盘读取了足够的数据来填充缓冲区,并且只有在到达文件末尾时才返回较少的数据。另一方面,从网络读取的流可能返回更少的数据,即使有更多的数据需要接收。

在使用通用解决方案之前,一定要检查您正在使用的特定流类的文档。

其他回答

如果你想要一个过程复制一个流到其他的一个,尼克张贴是好的,但它是丢失的位置重置,它应该是

public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[32768];
    long TempPos = input.Position;
    while (true)    
    {
        int read = input.Read (buffer, 0, buffer.Length);
        if (read <= 0)
            return;
        output.Write (buffer, 0, read);
    }
    input.Position = TempPos;// or you make Position = 0 to set it at the start
}

但如果它在运行时不使用过程,则应该使用内存流

Stream output = new MemoryStream();
byte[] buffer = new byte[32768]; // or you specify the size you want of your buffer
long TempPos = input.Position;
while (true)    
{
    int read = input.Read (buffer, 0, buffer.Length);
    if (read <= 0)
        return;
    output.Write (buffer, 0, read);
 }
    input.Position = TempPos;// or you make Position = 0 to set it at the start

区分“CopyStream”实现的基本问题是:

读取缓冲区的大小 写入的大小 我们是否可以使用多个线程(在读取时写入)。

这些问题的答案导致了CopyStream的巨大不同的实现,这取决于您拥有的流的类型和您试图优化的内容。“最佳”实现甚至需要知道流正在读取和写入的具体硬件。

我使用以下扩展方法。当一个流是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);
    }

不幸的是,没有真正简单的解决办法。你可以尝试这样做:

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知道复制数据的最佳方式。