9

どちらが良いですか:MemoryStream.WriteTo(Stream destinationStream)またはStream.CopyTo(Stream destinationStream)??

私はこのようにやっているので、私はバッファなしでこれらの2つの方法の比較について話している:

Stream str = File.Open("SomeFile.file");
MemoryStream mstr = new MemoryStream(File.ReadAllBytes("SomeFile.file"));

using(var Ms = File.Create("NewFile.file", 8 * 1024))
{
    str.CopyTo(Ms) or mstr.WriteTo(Ms);// Which one will be better??
}

アップデート

これが私がやりたいことです:

  • ファイルを開く[「X」タイプのファイルと言う]
  • 内容を解析する
  • ここからたくさんの新しいストリームを取得します[3〜4ファイル]
  • 1つのストリームを解析する
  • 何千ものファイルを抽出する[ストリームは画像ファイルです]
  • 他のストリームをファイルに保存
  • すべてのファイルを編集する
  • 新しい「X」タイプのファイルを生成します。

私は実際に正しく機能しているコードのすべてのビットを書きました。

しかし今、私はコードを最適化して最も効率的にしています。

4

6 に答える 6

17

同じことをする2つの方法があるのは歴史的な事故です。MemoryStreamには常にWriteTo()メソッドがあり、Streamは.NET 4までCopyTo()メソッドを取得しませんでした。

MemoryStream.WriteTo()バージョンは次のようになります。

public virtual void WriteTo(Stream stream)
{
    // Exception throwing code elided...
    stream.Write(this._buffer, this._origin, this._length - this._origin);
}

次のようなStream.CopyTo()の実装:

private void InternalCopyTo(Stream destination, int bufferSize)
{
    int num;
    byte[] buffer = new byte[bufferSize];
    while ((num = this.Read(buffer, 0, buffer.Length)) != 0)
    {
        destination.Write(buffer, 0, num);
    }
}

Stream.CopyTo()はより普遍的で、どのストリームでも機能します。また、たとえばNetworkStreamからデータをコピーするのを手探りするプログラマーを支援します。Read()からの戻り値に注意を払うのを忘れることは、非常に一般的なバグでした。ただし、もちろんバイトを2回コピーし、その一時的なものを割り当てますbuffer。MemoryStreamは、独自のバッファーから直接書き込むことができるため、これを必要としません。したがって、WriteTo()を引き続き使用することをお勧めします。違いに気付く可能性はほとんどありません。

于 2012-05-19T13:14:15.203 に答える
6

MemoryStream.WriteTo:このメモリストリームの内容全体を別のストリームに書き込みます。

Stream.CopyTo:現在のストリームからバイトを読み取り、宛先ストリームに書き込みます。コピーは、現在のストリームの現在の位置から開始されます。ソースストリーム全体をコピーするには、0に戻る必要があります。

したがって、MemoryStream.WriteToはこの状況に適したオプションだと思います

于 2012-05-19T10:51:45.677 に答える
4

を使用する場合Stream.CopyTo、最初にすべてのバイトをメモリに読み込む必要はありません。でも:

  • このコードは、使用したばかりの場合は簡単になりますFile.Copy
  • すべてのデータをメモリにロードする場合、次を使用できます。

    byte[] data = File.ReadAllBytes("input");
    File.WriteAllBytes("output", data);
    
  • using入力ストリームと出力ストリームのステートメントが必要です

本当に処理が必要で使用できない場合はFile.Copy、を使用すると、Stream.CopyToすべてをメモリにロードするよりも大きなファイルに対処できます。もちろん、それは必要ないかもしれませんし、他の理由でファイル全体をメモリにロードする必要があるかもしれません。

を持っている場合は、MemoryStreamおそらくではMemoryStream.WriteToなくを使用しますが、を使用するときにストリームの先頭にいることを確認する必要があることを除いStream.CopyToて、使用するものに大きな違いはないでしょう。CopyTo

于 2012-05-19T10:53:58.737 に答える
1

ハンス・パッサントのMemoryStream.WriteTo()のバグの主張は間違っていると思います。「Write()の戻り値を無視する」ことはありません。Stream.Write()はvoidを返します。これは、カウントバイト全体が書き込まれることを意味します。これは、Stream.Write()が、たとえばNetworkStreamへの操作を完了するために必要に応じてブロックするか、最終的に失敗した場合にスローすることを意味します。

これは、?nixでのwrite()システムコール、および「短い書き込み」を返す可能性のあるlibcなどでのその多くのエミュレーションとは実際に異なります。ハンスは、Stream.Write()がそれに続いているという結論に跳躍したのではないかと思います。これも私が予想していたことですが、明らかにそうではありません。

Stream.Write()は、その兆候を返すことなく「短い書き込み」を実行でき、呼び出し元はStreamのPositionプロパティが実際にカウントによって進められていることを確認する必要があると考えられます。これは非常にエラーが発生しやすいAPIであり、それが行われるかどうかは疑わしいですが、徹底的にテストしていません。(テストは少し注意が必要です。TCPNetworkStreamを、永久にブロックされたもう一方の端のリーダーに接続し、ワイヤーバッファーをいっぱいにするのに十分な書き込みを行う必要があると思います。またはそのようなもの...)

Stream.Write()のコメントは、明確ではありません。

概要:派生クラスでオーバーライドされると、バイトのシーケンスが現在のストリームに書き込まれ、書き込まれたバイト数だけこのストリーム内の現在の位置が進みます。パラメータ:バッファ:バイトの配列。このメソッドは、カウントバイトをバッファから現在のストリームにコピーします。

これをwrite(2)のLinuxのマニュアルページと比較してください。

write()は、bufを指すバッファーから、ファイル記述子fdによって参照されるファイルに最大カウントバイトを書き込みます。

重要な「まで」に注意してください。その文の後に、「短い書き込み」が発生する可能性のあるいくつかの条件の説明が続き、それが発生する可能性があることを非常に明確にしています。

これは本当に重要な問題です。間違いなく、Stream.Write()がどのように動作するかを知る必要があります。

于 2013-06-10T13:51:17.437 に答える
0

CopyToメソッドはバッファーを作成し、元のストリームからのデータをそのバッファーに入力してから、作成されたバッファーをパラメーターとして渡すWriteメソッドを呼び出します。WriteToは、memoryStreamの内部バッファを使用して書き込みます。それが違いです。何が良いか-どちらの方法を好むかはあなた次第です。

于 2012-05-19T11:04:13.697 に答える
0

Vb.NetのHttpInputStreamからMemoryStreamを作成します。

Dim filename As String = MyFile.PostedFile.FileName
Dim fileData As Byte() = Nothing
Using binaryReader = New BinaryReader(MyFile.PostedFile.InputStream)
    binaryReader.BaseStream.Position = 0
    fileData = binaryReader.ReadBytes(MyFile.PostedFile.ContentLength)
End Using
Dim memoryStream As MemoryStream = New MemoryStream(fileData)
于 2014-01-21T12:19:22.573 に答える