112

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

Dariusz Woźniak
  • 9,640
  • 6
  • 60
  • 73
Arbejdsglæde
  • 13,670
  • 26
  • 78
  • 144
  • This may be because you are creating a StreamWriter and StreamReader from the same MemoryStream. You might try using two different MemoryStreams: one for reader and one for writer. – NKamrath Jun 07 '12 at 15:13
  • Possible duplicate of http://stackoverflow.com/questions/2331675/cannot-access-closed-stream – Be Brave Be Like Ukraine Jun 07 '12 at 15:13
  • In some situations a solution can be based on creating a new `MemoryStream` based on using `MemoryStream.GetBuffer()` on the closed memory stream. See here: https://stackoverflow.com/a/50671919/253938 – RenniePet Jun 04 '18 at 06:26

7 Answers7

147

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();
}
Community
  • 1
  • 1
Thorsten Dittmar
  • 55,956
  • 8
  • 91
  • 139
  • There's little doubt there which I'm assuming why OP asked "What the best way to fix it ?" – Austin Salonen Jun 07 '12 at 15:18
  • What about close var sw = new StreamWriter(ms); var sr = new StreamReader(ms); ? – Arbejdsglæde Jun 07 '12 at 15:21
  • 1
    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. – Thorsten Dittmar Jun 07 '12 at 15:22
  • This code did not work for me. https://dotnetfiddle.net/UTBDAh, in compare to `leaveOpen` answer that did work. Or need `.Flush()` https://dotnetfiddle.net/69fBxR – Jaider Jul 25 '23 at 03:40
43

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());
    }
}
NtFreX
  • 10,379
  • 2
  • 43
  • 63
9

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.

d219
  • 2,707
  • 5
  • 31
  • 36
itsme86
  • 19,266
  • 4
  • 41
  • 57
2

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());
        }
}    
Alexey Subach
  • 11,903
  • 7
  • 34
  • 60
Massimiliano Peluso
  • 26,379
  • 6
  • 61
  • 70
1

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.

vcsjones
  • 138,677
  • 31
  • 291
  • 286
1

You have to leave the stream open to be able to read it. the "StreamWriter" closes it after it is done writing

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());                        
        }
    } //error here
}
Muhammed ASLAN
  • 151
  • 1
  • 5
0

In my case (admittedly very arcane and not likely to be reproduced often), this was causing the problem (this code is related to PDF generation using iTextSharp):

PdfPTable tblDuckbilledPlatypi = new PdfPTable(3);
float[] DuckbilledPlatypiRowWidths = new float[] { 42f, 76f };
tblDuckbilledPlatypi.SetWidths(DuckbilledPlatypiRowWidths);

The declaration of a 3-celled/columned table, and then setting only two vals for the width was what caused the problem, apparently. Once I changed "PdfPTable(3)" to "PdfPTable(2)" the problem went the way of the convection oven.

B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • 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?) – Sinatr Mar 04 '16 at 09:27