【问题标题】:How is the Stream.CopyTo(Stream) method implemented in .NET 4?Stream.CopyTo(Stream) 方法是如何在 .NET 4 中实现的?
【发布时间】:2009-12-19 18:26:43
【问题描述】:

.NET 4 中引入的一个有用的便利是 Stream.CopyTo(Stream[, Int32]),它从当前流中读取内容并将其写入另一个流。

这消除了对稍微乏味的code such as this的需要:

public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[32768];
    while (true)
    {
        int read = input.Read (buffer, 0, buffer.Length);
        if (read <= 0)
            return;
        output.Write (buffer, 0, read);
    }
}

由于我没有在这台机器上安装 .NET 4,我想知道是否有人安装了 .NET 4 可以打开 Reflector 并向我们展示框架类库团队如何为 .NET 4 实现此方法。

将它们的实现与上面的代码 sn-p 进行比较和对比。特别是,我很想知道选择了什么默认缓冲区大小。

【问题讨论】:

  • 复制在网络流上有效吗?
  • 好问题。不确定...也许安装了 .NET 4 的人之一可以尝试一下?
  • 它似乎可以在网络流上运行。

标签: .net .net-4.0


【解决方案1】:

在 .NET 4.5.1 中,它使用 81920 字节的固定缓冲区大小。 (早期版本的 .NET 使用 4096 字节的固定缓冲区大小,毫无疑问会随着时间的推移而不断变化。)还有一个重载,您可以传递自己的缓冲区大小。

该实现与您的非常相似,以一些改组和一些错误检查为模。 Reflector 将其核心渲染如下:

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);
  }
}

(您现在可以在http://referencesource.microsoft.com/#mscorlib/system/io/stream.cs#98ac7cf3acb04bb1 看到实际来源。)

错误检查基本上是围绕 input.CanRead 和 output.CanWrite 是否都为真,或者是否被处置。因此,在回答 Benny 的问题时,从 NetworkStream(或可写的 NetworkStream)复制应该非常高兴。

【讨论】:

  • 我想这个想法是只使用 1 页作为缓冲区?
  • 这是缓冲区大小的“快乐数字”。它不太可能完全落在页面边界上。
  • 它也足够小,不能分配在大对象堆上。
  • @itowlson 需要注意的是,默认缓冲区大小实际上是 81,920 字节,至少从 .NET 4.5.1 开始。这比文档声称的 4096 字节大 20 倍。您可以通过 CopyTo(Stream) 上的反射来确认这一点。你也可以在reference source看到它。
  • 这似乎有点低效,因为在很多情况下您可以并行读写(例如从网络读取并写入磁盘)。启用并发读/写的附加可选参数会很方便。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-26
  • 1970-01-01
  • 2012-08-01
  • 1970-01-01
  • 2011-10-16
  • 2011-05-01
  • 1970-01-01
相关资源
最近更新 更多