2012-09-09 35 views
7

Tôi đang cố gắng thêm một số dữ liệu vào luồng. Điều này hoạt động tốt với FileStream, nhưng không hoạt động với MemoryStream do kích thước bộ đệm cố định.Phụ thêm vào MemoryStream

Phương pháp ghi dữ liệu vào luồng được tách ra khỏi phương pháp tạo luồng (Tôi đã đơn giản hóa nó rất nhiều trong ví dụ bên dưới). Phương thức tạo luồng không biết chiều dài của dữ liệu được ghi vào luồng.

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); 
} 

Ý tưởng tôi đã gửi là có thể mở rộng MemoryStream đến hàm, sau đó nối dữ liệu được trả về vào dữ liệu hiện có.

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); 
} 

Bất kỳ giải pháp nào hiệu quả hơn?

+3

Bạn có thể giải thích tại sao bạn không sử dụng luồng có thể mở rộng cho cả hai bài viết không? – Rotem

+1

ah, như vậy? Luồng s2 = new MemoryStream(); // luồng bộ nhớ dung lượng có thể mở rộng s2.Write (existingData, 0, existingData.Length); WriteUnknownDataToStream (s2); –

+0

Vâng đó là điều tôi muốn nói ... đó là lý do tại sao đó là một luồng chứ không phải là một mảng, phải không? – Rotem

Trả lời

25

Giải pháp có thể là không giới hạn dung lượng của MemoryStream ngay từ đầu. Nếu bạn không biết trước tổng số byte bạn sẽ cần phải viết, hãy tạo MemoryStream với dung lượng không xác định và sử dụng nó cho cả hai lần viết.

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

này sẽ không nghi ngờ được ít performant hơn khởi tạo một MemoryStream từ một byte[], nhưng nếu bạn cần phải tiếp tục bằng văn bản cho dòng Tôi tin rằng đó là lựa chọn duy nhất của bạn.

+1

Nếu chênh lệch hiệu suất là quan trọng, bạn có thể [chỉ định dung lượng ban đầu của luồng] (http://msdn.microsoft.com/en-us/library/bx3c0489.aspx). Bằng cách này, nếu bạn đoán tốt (hoặc biết) kích thước cuối cùng, sẽ không có sự phân bổ lại. Nếu bạn đoán xấu, bạn sẽ lãng phí bộ nhớ hoặc có sự tái phân bổ ảnh hưởng đến hiệu suất, nhưng nó vẫn hoạt động. – svick

Các vấn đề liên quan