71

StreamReader.ReadToEndメソッドをエミュレートするエレガントなものはありBinaryReaderますか? おそらく、すべてのバイトをバイト配列に入れますか?

私はこれをします:

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

...しかし、もっと良い方法があるはずです。

4

6 に答える 6

103

元の回答(以下の更新をお読みください!)

単に行う:

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();
    }
    
}
于 2011-12-23T07:19:11.957 に答える
77

BinaryReader でこれを行う簡単な方法はありません。事前に読み取る必要があるカウントがわからない場合は、MemoryStream を使用することをお勧めします。

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

を呼び出すときに追加のコピーを回避するには、代わりに を介して and バッファをToArray()返すことができます。PositionGetBuffer()

于 2012-04-06T01:05:46.420 に答える
4

ストリームのコンテンツを別のストリームにコピーするために、ファイルの最後に到達するまで「いくつかの」バイトを読み取ることを解決しました。

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);                        
    }                
}
于 2014-05-16T13:26:10.630 に答える
0

この問題に対する別のアプローチは、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();
      }
   }
}

このアプローチを使用すると、再利用可能なコードと読み取り可能なコードの両方が可能になります。

于 2014-05-29T02:51:10.210 に答える
0

これは、基になるプロパティを利用して、BaseStream必要な長さ情報を提供します。それは物事を素晴らしくシンプルに保ちます。

以下に、 の 3 つの拡張メソッドを示しBinaryReaderます。

  • 最初は、ストリームの現在の位置から最後まで読み取ります
  • 2番目は、ストリーム全体を一度に読み取ります
  • 3 つ目は、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..);

于 2021-01-18T04:07:15.593 に答える
0

同じ問題がありました。
まず、FileInfo.Length を使用してファイルのサイズを取得します。
次に、バイト配列を作成し、その値を BinaryReader.ReadBytes(FileInfo.Length) に設定します。例えば

var size = new FileInfo(yourImagePath).Length;
byte[] allBytes = yourReader.ReadBytes(System.Convert.ToInt32(size));
于 2021-04-14T09:45:14.863 に答える