一尘不染

从流创建字节数组

c#

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

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

Stream s;
byte[] b;

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

读写流的块还是更好的主意吗?


阅读 208

收藏
2020-05-19

共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,它基本上等效于代码中的循环-创建the
MemoryStream,调用stream.CopyTo(ms)然后返回ms.ToArray()。任务完成。

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

上面的方法将继续读取(并复制到中MemoryStream),直到用完数据为止。然后,它要求传MemoryStream回阵列中资料的副本。如果你知道的大小-
开始,或 认为 你知道的大小,但是不肯定的-
你可以构造MemoryStream是该尺寸的开始。同样,您可以在末尾进行检查,如果流的长度与缓冲区的大小相同(由返回MemoryStream.GetBuffer),则可以仅返回缓冲区。因此,上面的代码没有得到最优化,但至少是正确的。它不承担关闭流的任何责任-
调用者应该这样做。

请参阅本文以获取更多信息(和替代实现)。

2020-05-19