【发布时间】:2010-09-12 20:37:43
【问题描述】:
我经常遇到一个问题,我有一个充满数据的流,并且想将它的所有内容写入另一个流。
所有代码示例都使用字节数组形式的缓冲区。
有没有更优雅的方法?
如果不是,缓冲区的理想大小是多少。哪些因素构成了这个值?
【问题讨论】:
我经常遇到一个问题,我有一个充满数据的流,并且想将它的所有内容写入另一个流。
所有代码示例都使用字节数组形式的缓冲区。
有没有更优雅的方法?
如果不是,缓冲区的理想大小是多少。哪些因素构成了这个值?
【问题讨论】:
关于理想的缓冲区大小:
"使用 Read 方法时,使用与流的内部缓冲区大小相同的缓冲区更有效,其中内部缓冲区设置为您想要的块大小,并且始终读取小于块大小。如果在构造流时未指定内部缓冲区的大小,则其默认大小为 4 KB(4096 字节)。"
任何读流的过程都会用到Read(char buffer[], int index, count),这就是这句话所指的方法。
http://msdn.microsoft.com/en-us/library/9kstw824.aspx(在“备注”下)。
【讨论】:
Read data in FileStream into a generic Stream
可能会有一些进入的方向
【讨论】:
我不确定您是否可以在 .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);
}
【讨论】:
我不知道比使用缓冲区更优雅的方式。
但是缓冲区的大小会有所不同。还记得关于 Vista 的文件复制的问题吗?原因是(基本上)改变了缓冲区大小。 this blogpost 中解释了这些更改。您可以从该帖子中了解主要因素。但是,这仅适用于文件复制。在应用程序中,您可能会执行大量内存副本,因此在这种情况下,4KB 可能是最佳缓冲区大小,as recommended by the .NET documentation。
【讨论】:
在.NET 4.0 中,我们终于得到了Stream.CopyTo 方法!耶!
【讨论】:
BufferedStream.CopyTo(流)
【讨论】:
正如一些人所建议的那样,CopyTo 和 CopyToAsync 应该可以完成这项工作。这是一个 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);
});
}
}
}
}
【讨论】: