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
。 -ビットシステム。
したがって、実際にはエレガントな方法はありません。
代わりに、@ianoの答えの次のバリエーションをお勧めします。このバリアントは.NET4に依存していません:
の拡張メソッドを作成します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();
}
}
を呼び出すときに追加のコピーを回避するには、代わりに を介して and バッファをToArray()
返すことができます。Position
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);
}
}
この問題に対する別のアプローチは、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();
}
}
}
このアプローチを使用すると、再利用可能なコードと読み取り可能なコードの両方が可能になります。
これは、基になるプロパティを利用して、BaseStream
必要な長さ情報を提供します。それは物事を素晴らしくシンプルに保ちます。
以下に、 の 3 つの拡張メソッドを示し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..);
同じ問題がありました。
まず、FileInfo.Length を使用してファイルのサイズを取得します。
次に、バイト配列を作成し、その値を BinaryReader.ReadBytes(FileInfo.Length) に設定します。例えば
var size = new FileInfo(yourImagePath).Length;
byte[] allBytes = yourReader.ReadBytes(System.Convert.ToInt32(size));