2012-09-09 15 views
7

ストリームにデータを追加しようとしています。これはFileStreamでうまく動作しますが、固定バッファーサイズのためにMemoryStreamでは正しく動作しません。MemoryStreamに追加

ストリームにデータを書き込むメソッドは、ストリームを作成するメソッドとは分離されています(下の例では大幅に簡略化しました)。ストリームを作成するメソッドは、ストリームに書き込まれるデータの長さを認識しません。

public void Foo(){ 
    byte[] existingData = System.Text.Encoding.UTF8.GetBytes("foo"); 
    Stream s1 = new FileStream("someFile.txt", FileMode.Append, FileAccess.Write, FileShare.Read); 
    s1.Write(existingData, 0, existingData.Length); 


    Stream s2 = new MemoryStream(existingData, 0, existingData.Length, true); 
    s2.Seek(0, SeekOrigin.End); //move to end of the stream for appending 

    WriteUnknownDataToStream(s1); 
    WriteUnknownDataToStream(s2); // NotSupportedException is thrown as the MemoryStream is not expandable 
} 

public static void WriteUnknownDataToStream(Stream s) 
{ 
    // this is some example data for this SO query - the real data is generated elsewhere and is of a variable, and often large, size. 
    byte[] newBytesToWrite = System.Text.Encoding.UTF8.GetBytes("bar"); // the length of this is not known before the stream is created. 
    s.Write(newBytesToWrite, 0, newBytesToWrite.Length); 
} 

私が持っていたアイデアは、既存のデータに返されたデータを追加し、その後、関数に拡張可能MemoryStreamを送信することでした。

public void ModifiedFoo() 
{ 
    byte[] existingData = System.Text.Encoding.UTF8.GetBytes("foo"); 
    Stream s2 = new MemoryStream(); // expandable capacity memory stream 

    WriteUnknownDataToStream(s2); 

    // append the data which has been written into s2 to the existingData 
    byte[] buffer = new byte[existingData.Length + s2.Length]; 
    Buffer.BlockCopy(existingData, 0, buffer, 0, existingData.Length); 
    Stream merger = new MemoryStream(buffer, true); 
    merger.Seek(existingData.Length, SeekOrigin.Begin); 
    s2.CopyTo(merger); 
} 

優れた(より効率的な)ソリューションはありますか?

+3

両方の書き込みで拡張ストリームを使用していない理由を説明してください。 – Rotem

+1

ああそう?ストリームs2 =新しいMemoryStream(); //拡張可能な容量のメモリストリーム s2.Write(existingData、0、existingData.Length); WriteUnknownDataToStream(s2); –

+0

はい、それは私の言いたいことです...それはストリームであり、配列ではありません、なぜですか? – Rotem

答えて

25

可能な解決策は、最初にMemoryStreamの容量を制限することではありません。 書き込みが必要な合計バイト数があらかじめ分かっていない場合は、容量が指定されていないMemoryStreamを作成し、両方の書き込みに使用します。

byte[] existingData = System.Text.Encoding.UTF8.GetBytes("foo"); 
MemoryStream ms = new MemoryStream(); 
ms.Write(existingData, 0, existingData.Length); 
WriteUnknownData(ms); 

これは間違いなくbyte[]からMemoryStreamを初期化するよりもパフォーマンスが低いことはないでしょうが、私はそれがあなたの唯一のオプションであると考えているストリームへの書き込みを継続する必要がある場合。

+1

パフォーマンスの違いが重要な場合は、[ストリームの初期容量を指定する]ことができます(http://msdn.microsoft.com/en-us/library/bx3c0489.aspx)。このようにして、最終サイズをよく知っている(または知っている)場合は、再割り当ては行われません。ひどく思うなら、パフォーマンスに影響を与えるメモリを浪費したり、再割り当てしたりしますが、それでも機能します。 – svick

関連する問題