如何在.net中将一个流的内容写入另一个流?

时间:2008-09-24 19:25:54

标签: .net stream

我经常遇到一个问题,即我有一个数据流,并希望将其中的所有数据写入另一个数据流。

所有代码示例都使用字节数组形式的缓冲区。

有更优雅的方法吗?

如果没有,那么缓冲区的理想大小是多少。哪些因素构成了这个价值?

7 个答案:

答案 0 :(得分:68)

在.NET 4.0中,我们终于得到了Stream.CopyTo方法!耶!

答案 1 :(得分:16)

关于理想的缓冲区大小:

“使用Read方法时,使用与流的内部缓冲区大小相同的缓冲区更有效,其中内部缓冲区设置为所需的块大小,并始终读取小于块大小。如果在构造流时未指定内部缓冲区的大小,则其默认大小为4千字节(4096字节)。“

任何流读取过程都将使用Read(char buffer [],int index,count),这是此引用引用的方法。

http://msdn.microsoft.com/en-us/library/9kstw824.aspx(在“备注”下)。

答案 2 :(得分:7)

我不确定你是否可以在.NET中直接将一个流传输到另一个流,但是这里有一个使用中间字节缓冲区的方法。缓冲区的大小是任意的。最有效的大小主要取决于您传输的数据量。

static void CopyStream(Stream input, Stream output){
    byte[] buffer = new byte[0x1000];
    int read;
    while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
        output.Write(buffer, 0, read);
}

答案 3 :(得分:5)

BufferedStream.CopyTo(流)

答案 4 :(得分:2)

Read data in FileStream into a generic Stream

可能会有一些指示进入

答案 5 :(得分:2)

我不知道比使用缓冲区更优雅的方式。

但是缓冲区的大小可以有所不同。还记得有关Vista文件复制的问题吗?这是(基本上)改变缓冲区大小的原因。 this blogpost解释了这些变化。您可以从该帖子中了解主要因素。但是,这仅适用于文件复制。在应用程序中,您可能会执行大量内存副本,因此在这种情况下,4KB可能是最佳缓冲区大小as recommended by the .NET documentation

答案 6 :(得分:0)

正如一些人所建议的那样,CopyToCopyToAsync 应该可以完成这项工作。下面是一个 TCP 服务器的示例,它侦听端口 30303 上的外部连接,并将它们与本地端口 8085(用 .NET 5 编写)进行管道传输。大多数流应该工作相同,只需注意它们是双向的还是单向的。

using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var externalConnectionListener = new TcpListener(IPAddress.Any, 30303);
            externalConnectionListener.Start();

            while (true)
            {
                var externalConnection = await externalConnectionListener.AcceptTcpClientAsync().ConfigureAwait(false);

                _ = Task.Factory.StartNew(async () =>
                  {
                      using NetworkStream externalConnectionStream = externalConnection.GetStream();
                      using TcpClient internalConnection = new TcpClient("127.0.0.1", 8085);
                      using NetworkStream internalConnectionStream = internalConnection.GetStream();

                      await Task.WhenAny(
                                externalConnectionStream.CopyToAsync(internalConnectionStream),
                                internalConnectionStream.CopyToAsync(externalConnectionStream)).ConfigureAwait(false);

                  });

            }
        }
    }
}