71

是否有一种优雅的方法来模拟该StreamReader.ReadToEnd方法BinaryReader?也许将所有字节放入一个字节数组中?

我这样做:

read1.ReadBytes((int)read1.BaseStream.Length);

...但必须有更好的方法。

4

6 回答 6

103

原始答案(阅读下面的更新!)

只需这样做:

byte[] allData = read1.ReadBytes(int.MaxValue);

文档说它将读取所有字节,直到到达流的末尾。


更新

尽管这看起来很优雅,并且文档似乎表明这会起作用,但实际实现(在 .NET 2、3.5 和 4 中检查)为数据分配了一个完整大小的字节数组,这可能会导致OutOfMemoryException32位系统。

因此,我会说实际上没有一种优雅的方式

相反,我会推荐@iano 答案的以下变体。此变体不依赖 .NET 4:为(或者,代码都相同)
创建扩展方法。BinaryReaderStream

public static byte[] ReadAllBytes(this BinaryReader reader)
{
    const int bufferSize = 4096;
    using (var ms = new MemoryStream())
    {
        byte[] buffer = new byte[bufferSize];
        int count;
        while ((count = reader.Read(buffer, 0, buffer.Length)) != 0)
            ms.Write(buffer, 0, count);
        return ms.ToArray();
    }
    
}
于 2011-12-23T07:19:11.957 回答
77

使用 BinaryReader没有简单的方法可以做到这一点。如果您不知道需要提前读取的计数,更好的选择是使用 MemoryStream:

public byte[] ReadAllBytes(Stream stream)
{
    using (var ms = new MemoryStream())
    {
        stream.CopyTo(ms);
        return ms.ToArray();
    }
}

为了避免调用时的额外副本ToArray(),您可以改为Position通过GetBuffer().

于 2012-04-06T01:05:46.420 回答
4

要将流的内容复制到另一个,我已经解决了读取“一些”字节的问题,直到到达文件末尾:

private const int READ_BUFFER_SIZE = 1024;
using (BinaryReader reader = new BinaryReader(responseStream))
{
    using (BinaryWriter writer = new BinaryWriter(File.Open(localPath, FileMode.Create)))
    {
        int byteRead = 0;
        do
        {
            byte[] buffer = reader.ReadBytes(READ_BUFFER_SIZE);
            byteRead = buffer.Length;
            writer.Write(buffer);
            byteTransfered += byteRead;
        } while (byteRead == READ_BUFFER_SIZE);                        
    }                
}
于 2014-05-16T13:26:10.630 回答
0

解决此问题的另一种方法是使用 C# 扩展方法:

public static class StreamHelpers
{
   public static byte[] ReadAllBytes(this BinaryReader reader)
   {
      // Pre .Net version 4.0
      const int bufferSize = 4096;
      using (var ms = new MemoryStream())
      {
        byte[] buffer = new byte[bufferSize];
        int count;
        while ((count = reader.Read(buffer, 0, buffer.Length)) != 0)
            ms.Write(buffer, 0, count);
        return ms.ToArray();
      }

      // .Net 4.0 or Newer
      using (var ms = new MemoryStream())
      {
         stream.CopyTo(ms);
         return ms.ToArray();
      }
   }
}

使用这种方法将允许可重用​​和可读的代码。

于 2014-05-29T02:51:10.210 回答
0

我使用它,它利用底层BaseStream属性为您提供所需的长度信息。它使事情变得简单而美好。

以下是三种扩展方法BinaryReader

  • 第一个从流的当前位置到末尾的任何位置读取
  • 第二个一口气读取整个流
  • 第三个利用Range类型来指定您感兴趣的数据子集。
public static class BinaryReaderExtensions {

    public static byte[] ReadBytesToEnd(this BinaryReader binaryReader) {
    
        var length = binaryReader.BaseStream.Length - binaryReader.BaseStream.Position;
        return binaryReader.ReadBytes((int)length);
    }
    
    public static byte[] ReadAllBytes(this BinaryReader binaryReader) {
    
        binaryReader.BaseStream.Position = 0;
        return binaryReader.ReadBytes((int)binaryReader.BaseStream.Length);
    }

    public static byte[] ReadBytes(this BinaryReader binaryReader, Range range) {

        var (offset, length) = range.GetOffsetAndLength((int)binaryReader.BaseStream.Length);
        binaryReader.BaseStream.Position = offset;
        return binaryReader.ReadBytes(length);      
    }
}

然后使用它们变得微不足道和清晰......

// 1 - Reads everything in as a byte array
var rawBytes = myBinaryReader.ReadAllBytes();

// 2 - Reads a string, then reads the remaining data as a byte array
var someString = myBinaryReader.ReadString();
var rawBytes = myBinaryReader.ReadBytesToEnd();

// 3 - Uses a range to read the last 44 bytes
var rawBytes = myBinaryReader.ReadBytes(^44..);

于 2021-01-18T04:07:15.593 回答
0

有同样的问题。
首先,使用 FileInfo.Length 获取文件的大小。
接下来,创建一个字节数组并将其值设置为 BinaryReader.ReadBytes(FileInfo.Length)。例如

var size = new FileInfo(yourImagePath).Length;
byte[] allBytes = yourReader.ReadBytes(System.Convert.ToInt32(size));
于 2021-04-14T09:45:14.863 回答