无法访问已关闭的记忆流

嗨,为什么 using (var sw = new StreamWriter(ms))返回 Cannot access a closed Stream exceptionMemory Stream在这段代码之上。

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
}

最好的解决办法是什么? 谢谢

203971 次浏览

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

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

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.

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.

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.

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

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
}