2012-09-09 76 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

啊,像这样? Stream s2 = new 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