2012-09-09 11 views
7

में शामिल होने से मैं कुछ डेटा को स्ट्रीम में जोड़ने की कोशिश कर रहा हूं। यह FileStream के साथ अच्छी तरह से काम करता है, लेकिन निश्चित बफर आकार के कारण 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

आह, ऐसा है? स्ट्रीम एस 2 = नई मेमोरीस्ट्रीम(); // विस्तार योग्य क्षमता मेमोरी स्ट्रीम s2.Write (मौजूदा डेटा, 0, मौजूदा डेटा। लम्बाई); लिखें अज्ञातडेटास्ट्रीम (एस 2); –

+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 आरंभ से कम performant होगा, लेकिन मेरा मानना ​​है कि यह अपने ही एकमात्र विकल्प है यदि आप धारा के लिए लिख जारी रखने की जरूरत है।

+1

यदि प्रदर्शन अंतर महत्वपूर्ण है, तो आप [स्ट्रीम की प्रारंभिक क्षमता निर्दिष्ट कर सकते हैं] (http://msdn.microsoft.com/en-us/library/bx3c0489.aspx)। इस तरह, यदि आप अंतिम आकार (या जानते हैं) का अनुमान लगाते हैं, तो कोई पुनर्वितरण नहीं होगा। यदि आप बुरी तरह से अनुमान लगाते हैं, तो आप स्मृति को बर्बाद कर देंगे या प्रदर्शन को प्रभावित करने वाले पुनर्विक्रय करेंगे, लेकिन यह अभी भी काम करेगा। – svick

संबंधित मुद्दे