2013-06-11 6 views
16

バイナリストリーム(つまりbyte[]配列)を使用する場合、BinaryReaderまたはBinaryWriterを使用する主なポイントは、プリミティブデータ型の読み取り/例えば、ReadBoolean()のようなメソッドを使用し、エンコーディングを考慮してストリームを生成します。それは全体の話ですか? BinaryReader/BinaryWriterを使用せずにStreamで直接作業する場合は、固有の利点または不利な点はありますか? Read()のようなほとんどのメソッドは、両方のクラスで同じように見えますが、私の推測は、それらが同じように下に動作するということです。 バイナリストリームを処理するためにStream.Read()とBinaryReader.Read()を使用する

は、2つの異なる方法でバイナリファイルを処理する簡単な例を考えてみましょう(編集:私はこの方法が無効であると認識し、バッファを使用することができ、それだけのサンプルです):

// Using FileStream directly 
using (FileStream stream = new FileStream("file.dat", FileMode.Open)) 
{ 
    // Read bytes from stream and interpret them as ints 
    int value = 0; 
    while ((value = stream.ReadByte()) != -1) 
    { 
     Console.WriteLine(value); 
    } 
} 


// Using BinaryReader 
using (BinaryReader reader = new BinaryReader(FileStream fs = new FileStream("file.dat", FileMode.Open))) 
{ 
    // Read bytes and interpret them as ints 
    byte value = 0;  
    while (reader.BaseStream.Position < reader.BaseStream.Length) 
    { 
     value = reader.ReadByte(); 
     Console.WriteLine(Convert.ToInt32(value)); 
    } 
} 

出力は以下となります同じですが、内部的には何が起こっていますか(OSの観点から)どの実装が使用されているかは、一般的に言えば重要ですか?彼らが提供する余分な方法を必要としない場合、BinaryReader/BinaryWriterを使用する目的はありますか?この特定のケースでは 、MSDNはStream.ReadByte()に関してこれを言う:

ストリーム上のデフォルトの実装は、新しいシングルバイト配列 を作成し、Readを呼び出します。これは正式なものですが、効率的でないのは です。 GC.GetTotalMemory()を使用

、この第1のアプローチは、第二の一つとして2倍として多くのスペースを割り当てるように見えるんが、より一般的なStream.Read()方法を使用してチャンクを読み込むために(例えば使用されている場合私の知る限り、これは場合であってはなりませんバッファ)。それでも、これらのメソッド/インターフェイスは簡単に統一されているようです。

+0

Stream.ReadByteのデフォルトの実装は、Streamの具体的な実装では無効になるように意図されています。どの質問に答えられていないのですか?ストリームに頼ることができるのではなく、新しいStreamReaderクラスが必要なのはなぜですか? – yoyo

+0

@yoyo一般的にStreamクラスがひどく設計されているためです。それはあまりにも "一般的"です。すべてのストリームがシークまたはReadByte(効率的)または読み書きをサポートするわけではありません。それはちょうど悪いOOPデザインです。代わりにインターフェイスを使用しているはずです。 –

答えて

11

いいえ、2つのアプローチの間には大きな違いはありません。余分なリーダーはいくつかのバッファリングを追加するので、それらを混ぜ合わせるべきではありません。ただし、パフォーマンスの大幅な差異は予想されません。すべてが実際のI/Oによって支配されています。

あなたが移動する(のみ)byte[]を持っているときに、

  • は、ストリームを使用しています。多くのストリーミングシナリオでは一般的です。
  • 他の基本タイプ(シンプルbyteを含む)を処理する場合は、BinaryWriterとBinaryReaderを使用してください。主な目的は、組み込みのフレームワークタイプをbyte[]に変換することです。
7

大きな違いは、I/Oをバッファリングする方法です。数バイトしか書いたり読んでいない場合は、BinaryWriter/BinaryReaderがうまくいきます。しかし、MBのデータを読まなければならない場合は、一度にbyteInt32などを読むのは少し遅くなります。代わりに、大きなチャンクを読み込んでそこから解析することもできます。

例:

// Using FileStream directly with a buffer 
using (FileStream stream = new FileStream("file.dat", FileMode.Open)) 
{ 
    // Read bytes from stream and interpret them as ints 
    byte[] buffer = new byte[1024]; 
    int count; 
    // Read from the IO stream fewer times. 
    while((count = stream.Read(buffer, 0, buffer.Length)) > 0) 
     for(int i=0; i<count; i++) 
      Console.WriteLine(Convert.ToInt32(buffer[i])); 
} 

今これは少しオフトピックです...しかし、私はそこにそれを投げるでしょう: をあなたは非常に狡猾な取得したい場合は...と本当に自分でパフォーマンスの向上を与えます...この例では、注意すべきこと

// Using FileStream directly with a buffer and BlockCopy 
using (FileStream stream = new FileStream("file.dat", FileMode.Open)) 
{ 
    // Read bytes from stream and interpret them as ints 
    byte[] buffer = new byte[1024]; 
    int[] intArray = new int[buffer.Length >> 2]; // Each int is 4 bytes 
    int count; 
    // Read from the IO stream fewer times. 
    while((count = stream.Read(buffer, 0, buffer.Length)) > 0) 
    { 
     // Copy the bytes into the memory space of the Int32 array in one big swoop 
     Buffer.BlockCopy(buffer, 0, intArray, count); 

     for(int i=0; i<count; i+=4) 
      Console.WriteLine(intArray[i]); 
    } 
} 

いくつかのこと:この1つは取る代わりEACH Int32を解析する(それは危険と考えられるかもしれない、とはいえ)、あなたはBuffer.BlockCopy()

別の例を使用して一度にすべてを行うことができます1の代わりに4バイトのInt32 ...これは異なる結果をもたらします。また、Int32以外の他のデータ型に対してもこれを行うことができますが、マーシャリングはあなたの心の中にあるべきだと主張する人がいます。 (私はちょうど何かについて考えることを提示したい...)

+0

ありがとうございます。私が提供した例は仮説ですが、実際の大容量ファイルには効果がないことに気付きました。この場合、常にバッファリングされた方法(最初の例)を実行します。私が理解しているように、 'Stream.Read()'と 'BinaryReader.Read()'は同じことを可能にします。また、.NET 4以降、 'Stream.CopyTo()'がこれを行います。 – w128

+1

もう1つのことは、TCPハンドのように何かをしている場合です。一度に1バイトを書き、クライアントがブロックを読み込むと問題が発生します。この場合、私が書くたびにブロックで行い、読むと 'BinaryReader'で読みます。このように、私はカバーされます。 – Andrew

+0

Andrew:このようなシナリオでは、どちらの場合でも1バイトのバッファを使用する場合、 'Stream.Read()'と 'BinaryReader.Read()'の両方を使って同じ振る舞いをすると思います。 – w128

関連する問題