Элегантный способ использовать (все байты) BinaryReader? - PullRequest
59 голосов
/ 23 декабря 2011

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

Я делаю это:

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

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

Ответы [ 4 ]

89 голосов
/ 23 декабря 2011

Просто сделайте:

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

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


Обновление

Хотя это кажется элегантным, и документация, кажется, указывает, что это будет работать, фактическая реализация (проверено в .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();
    }

}
68 голосов
/ 06 апреля 2012

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

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

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

3 голосов
/ 16 мая 2014

Чтобы скопировать содержимое потока в другой, я решил прочитать «некоторые» байты, пока не будет достигнут конец файла:

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);                        
    }                
}
0 голосов
/ 29 мая 2014

Другой подход к этой проблеме - использовать методы расширения 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();
      }
   }
}

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

...