一种优雅的消费方式(a的所有字节)BinaryReader?

时间:2011-12-23 07:05:13

标签: c# .net stream streamreader binaryreader

使用StreamReader.ReadToEnd模仿BinaryReader方法是否优雅?也许将所有字节都放入一个字节数组中?

我这样做:

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

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

6 个答案:

答案 0 :(得分:89)

简单地说:

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

documentation表示它将读取所有字节,直到到达流的末尾。


更新

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

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

相反,我会推荐@ iano的答案的以下变体。此变体不依赖于.NET 4:
BinaryReader(或Stream创建扩展方法,代码与之相同。

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

}

答案 1 :(得分:68)

使用BinaryReader没有简单方法。如果您不知道需要提前阅读的计数,最好的办法是使用MemoryStream:

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

要在拨打ToArray()时避免使用其他副本,您可以通过Position返回GetBuffer()和缓冲区。

答案 2 :(得分:3)

要将流的内容复制到另一个,我已经解决了阅读"一些"到达文件末尾的字节数:

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

答案 3 :(得分: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..);

答案 4 :(得分:0)

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

var size = new FileInfo(yourImagePath).Length;
byte[] allBytes = yourReader.ReadBytes(System.Convert.ToInt32(size));

答案 5 :(得分:-1)

解决此问题的另一种方法是使用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();
      }
   }
}

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