从 C# 中的 Stream 创建字节数组:2025 年 5 大最佳实践

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

将 Stream 转换为字节数组:C# 开发者指南(2025 版)



您是否曾有过这样的想法:“为什么,C#,你就不能让我用一行代码就把这个 Stream 转换成字节数组呢?”。如果是这样——您并不孤单。在 Stack Overflow 上,“从 stream 创建字节数组”这个问题获得了数千次浏览,这并非偶然。看似一个基本任务,但魔鬼总在细节中:性能、内存、异步性和 .NET 版本。



在 2025 年,.NET 生态系统为我们提供了几种优雅的解决方案。在本文中,我们将探讨 5 种最佳实践——从经典方法到新方法。您将了解何时使用 MemoryStream,为什么 BinaryReader 仍然适用,以及如何处理大型流而不会导致应用程序崩溃。让我们开始吧!



1. 经典方法:MemoryStream 和 CopyTo



最流行且最直观的方法。如果您有一个 Stream(例如,来自文件、网络或内存),您只需将其“复制”到 MemoryStream,然后调用 ToArray()。



public static byte[] StreamToBytesUsingMemoryStream(Stream inputStream){    using (var memoryStream = new MemoryStream())    {        inputStream.CopyTo(memoryStream);        return memoryStream.ToArray();    }}


优点:

  • 简单且可读性强。
  • 适用于所有 .NET 版本(Framework、Core、5+)。
  • 支持 CopyToAsync 进行异步操作。


缺点:

  • 如果流很大(例如 1 GB),数据会在内存中保存两次:一次在 MemoryStream 中,一次在数组中。
  • 对于非常小的流来说不是最快的选择(创建对象的开销)。


何时使用: 适用于中等大小的流(最多 100 MB),并且代码可读性比微优化更重要时。



2. 异步英雄:ReadAsync 和 Buffer



在现代开发中,异步是标准。 ReadAsync 方法允许您分块读取数据,而不会阻塞线程。这在 ASP.NET Core 或 GUI 应用程序中特别有用。



public static async Task<byte[]> StreamToBytesAsync(Stream inputStream){    using (var memoryStream = new MemoryStream())    {        byte[] buffer = new byte[8192]; // 8 KB — 标准大小        int bytesRead;        while ((bytesRead = await inputStream.ReadAsync(buffer, 0, buffer.Length)) > 0)        {            await memoryStream.WriteAsync(buffer, 0, bytesRead);        }        return memoryStream.ToArray();    }}


专业建议: 缓冲区大小可以更改。对于网络流,8 KB 是黄金分割点。对于 SSD 磁盘,可以增加到 64 KB。



优点:

  • 不阻塞调用线程。
  • 允许“即时”处理数据(例如,计算哈希值)。
  • 控制内存消耗。


缺点:

  • 代码稍多。
  • 需要理解 async/await 模式。


3. BinaryReader:老朋友胜过新朋友



许多人忘记了 BinaryReader,但这是错误的。它可以用一个命令读取整个流——ReadBytes。但有一个问题:它需要预先知道流的长度。



public static byte[] StreamToBytesUsingBinaryReader(Stream inputStream){    if (inputStream.CanSeek)    {        inputStream.Position = 0; // 如果需要,重置位置        using (var reader = new BinaryReader(inputStream, Encoding.UTF8, leaveOpen: true))        {            return reader.ReadBytes((int)inputStream.Length);        }    }    else    {        throw new InvalidOperationException("Stream 不支持查找                

博客

书籍推荐