MemoryStream - Cannot access a closed Stream

175,423

Solution 1

This is because the StreamReader closes the underlying stream automatically when being disposed of. The using statement does this automatically.

However, the StreamWriter you're using is still trying to work on the stream (also, the using statement for the writer is now trying to dispose of the StreamWriter, which is then trying to close the stream).

The best way to fix this is: don't use using and don't dispose of the StreamReader and StreamWriter. See this question.

using (var ms = new MemoryStream())
{
    var sw = new StreamWriter(ms);
    var sr = new StreamReader(ms);

    sw.WriteLine("data");
    sw.WriteLine("data 2");
    ms.Position = 0;

    Console.WriteLine(sr.ReadToEnd());                        
}

If you feel bad about sw and sr being garbage-collected without being disposed of in your code (as recommended), you could do something like that:

StreamWriter sw = null;
StreamReader sr = null;

try
{
    using (var ms = new MemoryStream())
    {
        sw = new StreamWriter(ms);
        sr = new StreamReader(ms);

        sw.WriteLine("data");
        sw.WriteLine("data 2");
        ms.Position = 0;

        Console.WriteLine(sr.ReadToEnd());                        
    }
}
finally
{
    if (sw != null) sw.Dispose();
    if (sr != null) sr.Dispose();
}

Solution 2

Since .net45 you can use the LeaveOpen constructor argument of StreamWriter and still use the using statement. Example:

using (var ms = new MemoryStream())
{
    using (var sw = new StreamWriter(ms, leaveOpen:true))
    {
        sw.WriteLine("data");
        sw.WriteLine("data 2");    
    }

    ms.Position = 0;
    using (var sr = new StreamReader(ms))
    {
        Console.WriteLine(sr.ReadToEnd());
    }
}

Solution 3

When the using() for your StreamReader is ending, it's disposing the object and closing the stream, which your StreamWriter is still trying to use.

Solution 4

The problem is this block:

using (var sr = new StreamReader(ms))
{
    Console.WriteLine(sr.ReadToEnd());                        
}

When the StreamReader is closed (after leaving the using), it closes it's underlying stream as well, so now the MemoryStream is closed. When the StreamWriter gets closed, it tries to flush everything to the MemoryStream, but it is closed.

You should consider not putting the StreamReader in a using block.

Solution 5

when it gets out from the using statement the Dispose method will be called automatically closing the stream

try the below:

using (var ms = new MemoryStream())
{
    var sw = new StreamWriter(ms);

        sw.WriteLine("data");
        sw.WriteLine("data 2");
        ms.Position = 0;
        using (var sr = new StreamReader(ms))
        {
            Console.WriteLine(sr.ReadToEnd());
        }
}    
Share:
175,423
Arbejdsglæde
Author by

Arbejdsglæde

Certificated Sitecore Developer. CMS Sitecore is my favorite.

Updated on July 08, 2022

Comments

  • Arbejdsglæde
    Arbejdsglæde almost 2 years

    Hi why using (var sw = new StreamWriter(ms)) returns Cannot access a closed Stream exception. Memory Stream is on top of this code.

    using (var ms = new MemoryStream())
    {
        using (var sw = new StreamWriter(ms))
        {                 
            sw.WriteLine("data");
            sw.WriteLine("data 2");
            ms.Position = 0;
            using (var sr = new StreamReader(ms))
            {
                Console.WriteLine(sr.ReadToEnd());                        
            }
        } //error here
    }
    

    What the best way to fix it ? Thanks

  • and_the_rand
    and_the_rand about 12 years
    There's little doubt there which I'm assuming why OP asked "What the best way to fix it ?"
  • and_the_rand
    and_the_rand about 12 years
    There's little doubt there which I'm assuming why OP asked "What the best way to fix it ?"
  • Arbejdsglæde
    Arbejdsglæde about 12 years
    What about close var sw = new StreamWriter(ms); var sr = new StreamReader(ms); ?
  • Thorsten Dittmar
    Thorsten Dittmar about 12 years
    You don't need to worry about them. I quote the accepted answer from the question I linked: You should be OK by leaving the StreamReader go out of scope if you need to use the underlying stream directly. Just make sure you dispose the underlying stream manually when it's appropriate. In other words: while the reader and writer are not disposed of explicitly, they will be garbage collected in the end. But I'll edit again to give another possible solution.
  • Sinatr
    Sinatr over 8 years
    This should be another question + answer. It has nothing to do with OP problem. While it may be very useful to iTextSharp users the way you provide help to others is wrong (putting it into random question with only similar exception text?)
  • Jan
    Jan over 5 years
    +1 for mentioning, can also be used without "using"-Statement. (my underlying MemoryStream needs to stay alive) and -1 to Microsoft for forcing me into that ugly ctor. ^^
  • Giannis Paraskevopoulos
    Giannis Paraskevopoulos over 3 years
    @Jan you could use new StreamWriter(ms, leaveOpen:true) which i guess is a bit less ugly