3

のバイトをIEnumerable<byte>ファイルに書き込む必要があります。
私はそれを配列に変換してWrite(byte[])メソッドを使用することができます:

using (var stream = File.Create(path))
    stream.Write(bytes.ToArray());

ただしIEnumerable、コレクションのアイテム数は提供されないため、絶対に必要な場合を除いてToArray、使用はお勧めしません。

したがって、を繰り返して、各繰り返しIEnumerableで使用できます。WriteByte(byte)

using (var stream = File.Create(path))
    foreach (var b in bytes)
        stream.WriteByte(b);

たくさんのデータを書くとき、どちらが速いのだろうか。

Write(byte[])を使用すると、配列のサイズに応じてバッファが設定されるため、配列に関してはより高速になると思います。

私の質問は、IEnumerable<byte>MBのデータがある場合、どちらのアプローチが優れているかということです。それを配列に変換して呼び出すWrite(byte[])か、それとも繰り返してWriteByte(byte)それぞれを呼び出しますか?

4

2 に答える 2

3

大量のバイトストリームを列挙することは、通常は安価なものに大量のオーバーヘッドを追加するプロセスです。つまり、あるバッファから次のバッファにバイトをコピーします。

通常、LINQスタイルのオーバーヘッドはそれほど重要ではありませんが、通常のハードドライブで1秒あたり1億バイトを処理する場合、深刻なオーバーヘッドに気付くでしょう。これは時期尚早の最適化ではありません。これはパフォーマンスのホットスポットになると予測できるため、熱心に最適化する必要があります。

IEnumerableしたがって、バイトをコピーするときは、おそらく、のような抽象化にまったく依存すべきではありませんIList。およびを含む配列またはArraySegement<byte>'を渡します。これにより、アレイを頻繁にスライスする必要がなくなります。OffsetCount

ハイスループットIOを伴う死の罪でもあることの1つは、バイトごとにメソッドを呼び出すことです。バイト単位での読み取りとバイト単位での書き込みのように。これらのメソッドは1秒間に何億回も呼び出される必要があるため、これによりパフォーマンスが低下します。私はそれを自分で経験しました。

一度に少なくとも4096バイトのバッファ全体を常に処理します。IOを実行しているメディアに応じて、はるかに大きなバッファー(64k、256k、さらにはメガバイト)を使用できます。

于 2012-09-22T17:51:19.950 に答える
1

どのバージョンが速いかをプロファイリングする必要があります。このクラスには、実際のファイルシステムアクセスからメソッドとメソッドを少しFileStream分離する内部バッファがあります。Read()Write()

コンストラクターでバッファーサイズを指定しない場合FileStream、デフォルトで4096バイトのバッファーのようなものが使用されます。WriteByte()そのバッファは、基になるファイルへの1回の書き込みに多くの呼び出しを結合します。唯一の問題は、通話のオーバーヘッドがWriteByte()通話のオーバーヘッドを超えるかどうかEnumerable.ToArray()です。後者は間違いなくより多くのメモリを使用しますが、常にこの種のトレードオフに対処する必要があります。

参考:現在の.NET 4の実装でEnumerable.ToArray()は、必要に応じてサイズを複製してアレイを拡張します。大きくなるたびに、すべての値がコピーされます。また、すべてのアイテムが配列に格納されると、そのコンテンツは最終サイズの配列に再度コピーされます。IEnumerable<T>実際に実装するインスタンスの場合、コードはそのICollection<T>事実を利用して正しい配列サイズで開始し、代わりにコレクションをコピーします。

于 2012-09-22T18:14:31.293 に答える