2012-07-17 29 views
9

In meinem Programm lese ich grundsätzlich in einer Datei, führe eine Verarbeitung durch und übergebe sie dann als Hauptspeicher an den Hauptspeicher, der von einem Streamreader verarbeitet wird. Dies wird alles von einer Klasse neben meiner Hauptperson gehandhabt.MemoryStream deaktiviert das Lesen nach der Rückgabe

Das Problem ist, wenn ich den Speicherstrom von meiner Methode in einer anderen Klasse zurückgibt, wird die Variable "Canread" auf false festgelegt und verursacht daher die Initialisierung des Streamreaders fehlschlagen.

Unten ist ein Beispiel für das Problem geschieht (wenn auch hier auf die Memorystream in der anderen Klasse Ich schreibe, aber es verursacht immer noch den gleichen Fehler, wenn ich es passieren zurück.

In der Klasse mit dem Namen " Other ":

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

die Funktion ruft im Hauptprogramm:

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

Wenn ich einen Haltepunkt setzen auf die‚Rückkehr MemStream‘, die‚CanRead‘Eigenschaft ist nach wie vor auf wahr gesetzt. Sobald ich so gehe, dass es zu meiner Hauptfunktion zurückkehrt und den zurückgegebenen Wert in MStream schreibt, wird die Eigenschaft "CanRead" auf false gesetzt. Dies verursacht dann eine Ausnahme in StreamReader, die besagt, dass MStream nicht gelesen werden konnte (wie die Eigenschaft angegeben wurde). Die Daten befinden sich im Stream-Puffer, wie es sein sollte, aber ich kann es einfach nicht rausbekommen.

Wie stelle ich es so ein, dass "CanRead" true meldet, sobald es an meine Hauptleitung zurückgegeben wird? Oder verstehe ich nicht, wie MemoryStream funktioniert und wie würde ich erreichen, was ich tun möchte?

Antwort

21

Das ist das Problem:

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

    return MemStream; 
} 

Sie schließen die Verfasser, die die MemoryStream schließt. In diesem Fall möchten Sie das nicht tun ... obwohl Sie müssen den Schriftsteller spülen, und spulen Sie die MemoryStream. Ändern Sie einfach Ihren Code:

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, was passiert, wenn 'writer' GC'd vor' stream' verwendet wird? –

+2

@KevinBrock: Dann ist es nur Müll gesammelt, und alle gepufferten Daten sind verloren. 'StreamWriter' hat keinen Finalizer, AFAIK. –

+0

Das war genau das. Ich dachte, dass die Rücksendung eine nicht-geschlossene Version aussenden würde, bevor die Verwendung den Streamwriter entsorgen würde. Ich denke, ich dachte, dass die Rückkehr eine Kopie des MemoryStream zurückgeben würde, keine Referenz aus irgendeinem Grund.Ich dachte auch, dass das Verlassen der ImportantStreamManipulator-Methode über eine Rückgabe automatisch den Streamwriter sowieso entsorgen würde, so dass ich nicht sicher war, dass dies möglich war. Wird der Streamwriter irgendwann später im Programm über den GC entsorgt, oder wird er erst entsorgt, wenn ich den MemoryStream entsorgt habe oder das Programm geschlossen habe? – Xantham

0

Wie andere gesagt haben, das Problem ist, dass der Strom geschlossen wird, wenn die Stream geschlossen ist. Eine Möglichkeit, dies zu umgehen, ist die Rückgabe eines Byte-Arrays anstelle eines MemoryStream. Dadurch werden potenziell lange laufende Objekte vermieden, die vom Garbage Collector entsorgt werden müssen.

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

Eine andere Methode besteht darin, den Stream vor der Rückgabe in einen anderen Stream zu kopieren. Dies hat jedoch weiterhin das Problem, dass der nachfolgende Zugriff darauf mit einem StreamReader diesen Stream schließen wird.

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()); 
    } 
} 
Verwandte Themen