Элегантный способ потребления (все байты a) BinaryReader?

Есть ли элегантный способ эмулировать метод StreamReader.ReadToEnd с помощью BinaryReader? Возможно, положить все байты в байтовый массив?

Я делаю это:

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

... но должен быть лучший способ.

Ответ 1

Просто выполните:

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

Документация говорит, что она будет читать все байты до тех пор, пока не будет достигнут конец потока.


Update

Хотя это кажется изящным, и в документации, как представляется, указывается, что это будет работать, фактическая реализация (отмеченная в .NET 2, 3.5 и 4) распределяет полноразмерный байтовый массив для данные, которые, вероятно, вызовут OutOfMemoryException в 32-битной системе.

Поэтому я бы сказал, что на самом деле нет элегантного способа.

Вместо этого я бы рекомендовал следующий вариант ответа @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();
    }

}

Ответ 2

Существует не легкий способ сделать это с помощью BinaryReader. Если вы не знаете счет, который вам нужно прочитать раньше времени, лучше использовать MemoryStream:

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

Чтобы избежать дополнительной копии при вызове ToArray(), вместо этого вы можете вернуть Position и buffer через GetBuffer().

Ответ 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);                        
    }                
}

Ответ 4

Другим подходом к этой проблеме является использование методов расширения С#:

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

Использование этого подхода позволит использовать как многоразовый, так и читаемый код.