Есть ли элегантный способ эмулировать метод StreamReader.ReadToEnd
с помощью BinaryReader
? Возможно, положить все байты в байтовый массив?
Я делаю это:
read1.ReadBytes((int)read1.BaseStream.Length);
... но должен быть лучший способ.
Есть ли элегантный способ эмулировать метод StreamReader.ReadToEnd
с помощью BinaryReader
? Возможно, положить все байты в байтовый массив?
Я делаю это:
read1.ReadBytes((int)read1.BaseStream.Length);
... но должен быть лучший способ.
Просто выполните:
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();
}
}
Существует не легкий способ сделать это с помощью BinaryReader. Если вы не знаете счет, который вам нужно прочитать раньше времени, лучше использовать MemoryStream:
public byte[] ReadAllBytes(Stream stream)
{
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
return ms.ToArray();
}
}
Чтобы избежать дополнительной копии при вызове ToArray()
, вместо этого вы можете вернуть Position
и buffer через GetBuffer()
.
Чтобы скопировать содержимое потока в другой, я решил прочитать "некоторые" байты до тех пор, пока не будет достигнут конец файла:
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);
}
}
Другим подходом к этой проблеме является использование методов расширения С#:
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();
}
}
}
Использование этого подхода позволит использовать как многоразовый, так и читаемый код.