小编典典

从流中创建字节数组

all

从输入流创建字节数组的首选方法是什么?

这是我当前使用 .NET 3.5 的解决方案。

Stream s;
byte[] b;

using (BinaryReader br = new BinaryReader(s))
{
    b = br.ReadBytes((int)s.Length);
}

读取和写入流的块仍然是一个更好的主意吗?


阅读 198

收藏
2022-02-28

共1个答案

小编典典

这真的取决于你是否可以信任s.Length。对于许多流,您只是不知道会有多少数据。在这种情况下——在 .NET 4 之前——我会使用这样的代码:

public static byte[] ReadFully(Stream input)
{
    byte[] buffer = new byte[16*1024];
    using (MemoryStream ms = new MemoryStream())
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, read);
        }
        return ms.ToArray();
    }
}

对于 .NET 4 及更高版本,我会使用Stream.CopyTo,这基本上相当于我的代码中的循环 - 创建MemoryStream
调用stream.CopyTo(ms)然后返回ms.ToArray()。任务完成。

我也许应该解释为什么我的答案比其他人长。Stream.Read不保证它会读取它所要求的所有内容。例如,如果您正在从网络流中读取数据,它可能会读取一个数据包的值然后返回,即使很快会有更多数据。BinaryReader.Read将一直持续到流结束或您指定的大小,但您仍然必须知道开始的大小。

上述方法将继续读取(并复制到 a
MemoryStream),直到数据用完。然后它要求MemoryStream返回数组中数据的副本。如果您知道开始的大小 - 或者 认为
您知道大小,但不确定 - 您可以将 构建MemoryStream为开始的大小。同样,您可以在最后进行检查,如果流的长度与缓冲区的大小相同(由
返回MemoryStream.GetBuffer),那么您可以只返回缓冲区。所以上面的代码不是很优化,但至少是正确的。它不承担关闭流的任何责任——调用者应该这样做。

有关更多信息(和替代实现),请参阅本文。

2022-02-28