2012-07-17 72 views
9

在我的程序的時候,我基本上是讀文件,做一些處理,然後將其傳遞迴主程序作爲一個MemoryStream,這將是一個StreamReader來處理。這將全部由我旁邊的一堂課來處理。的MemoryStream禁用讀返回

的問題是,當我在另一個類從我的方法返回的內存流的「的CanRead」變量設置爲false,從而導致StreamReader的初始化失敗。

下面是發生(儘管在這裏我寫在其他類中的MemoryStream的問題的一個例子,但它還是引起了同樣的錯誤,當我通過了回去。

中命名的類「 Otherclass「:

public static MemoryStream ImportantStreamManipulator() 
{ 
    MemoryStream MemStream = new MemoryStream(); 

    StreamWriter writer = new StreamWriter(MemStream); 
    using (writer) 
    { 
     //Code that writes stuff to the memorystream via streamwriter 

     return MemStream; 
    } 
} 

功能的主程序調用:

MemoryStream MStream = Otherclass.ImportantStreamManipulator(); 
StreamReader reader = new StreamReader(MStream); 

當我把一個斷點 」迴歸MemStream「 中, 」的CanRead「 屬性仍然設置爲true。一旦我回到我的主函數,並將返回的值寫入MStream,「CanRead」屬性設置爲false。這會導致StreamReader發生異常,說MStream無法讀取(如屬性所示)。這些數據應該是在流緩衝區中,但我無法解決。

如何設置它,以便「的CanRead」一旦回到我的主會報告是真的嗎?或者我誤解了MemoryStream的工作原理以及如何完成我想要做的事情?

回答

21

這就是問題所在:

using (writer) 
{ 
    //Code that writes stuff to the memorystream via streamwriter 

    return MemStream; 
} 

您要關閉的作家,其封閉MemoryStream。在這種情況下,你不想這樣做...儘管你確實需要沖洗作家和倒帶的MemoryStream。只要將您的代碼更改爲:

public static MemoryStream ImportantStreamManipulator() 
{ 
    // Probably add a comment here stating that the lack of using statements 
    // is deliberate. 
    MemoryStream stream = new MemoryStream(); 

    StreamWriter writer = new StreamWriter(stream); 
    // Code that writes stuff to the memorystream via streamwriter 

    writer.Flush(); 
    stream.Position = 0; 
    return stream; 
} 
+0

Jon,如果在使用'stream'前'writer'爲GC'd會發生什麼? – 2012-07-17 18:47:43

+2

@KevinBrock:然後,它只是收集垃圾,任何緩衝的數據都將丟失。 'StreamWriter'沒有終結者AFAIK。 – 2012-07-17 18:50:33

+0

就是這樣。我認爲返回它會在使用之前發出一個非關閉版本來處理這個Streamwriter。我想我在考慮返回將返回一個MemoryStream的副本,而不是由於某種原因的參考。我也認爲通過返回離開ImportantStreamManipulator方法會自動處理流寫入器,所以我不確定這是可能的。是否可以通過GC在程序中稍後處理Streamwriter,還是僅在處理MemoryStream或關閉程序後才處理? – Xantham 2012-07-17 18:51:05

0

正如其他人所述,問題在於StreamWriter關閉時Stream已關閉。處理這個問題的一種可能方式是返回一個字節數組而不是MemoryStream。這樣可以避免垃圾收集器必須處理的可能長時間運行的對象。

public static void Main() 
{ 
    OutputData(GetData()); 
} 

public static byte[] GetData() 
{ 
    byte[] binaryData = null; 

    using (MemoryStream ms = new MemoryStream()) 
    using (StreamWriter sw = new StreamWriter(ms)) 
    { 
     string data = "My test data is really great!"; 

     sw.Write(data); 
     sw.Flush(); 

     binaryData = ms.ToArray(); 
    } 

    return binaryData; 
} 

public static void OutputData(byte[] binaryData) 
{ 
    using (MemoryStream ms = new MemoryStream(binaryData)) 
    using (StreamReader sr = new StreamReader(ms)) 
    { 
     Console.WriteLine(sr.ReadToEnd()); 
    } 
} 

另一種方法是在返回之前將流複製到另一個流。但是,這仍然存在隨後使用StreamReader訪問它會關閉該流的問題。

public static void RunSnippet() 
{ 
    OutputData(GetData()); 
} 

public static MemoryStream GetData() 
{ 
    MemoryStream outputStream = new MemoryStream(); 

    using (MemoryStream ms = new MemoryStream()) 
    using (StreamWriter sw = new StreamWriter(ms)) 
    { 
     string data = "My test data is really great!"; 

     sw.Write(data); 
     sw.Flush(); 

     ms.WriteTo(outputStream); 
     outputStream.Seek(0, SeekOrigin.Begin); 
    } 

    return outputStream; 
} 

public static void OutputData(MemoryStream inputStream) 
{ 
    using (StreamReader sr = new StreamReader(inputStream)) 
    { 
     Console.WriteLine(sr.ReadToEnd()); 
    } 
}