为什么
using (var sw = new StreamWriter(ms))
返回 Cannot access a closed Stream
exception
,而 MemoryStream
位于此代码之上?
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
}
这是因为
StreamReader
在被处置时会自动关闭底层流。 using
语句会自动执行此操作。
但是,您正在使用的
StreamWriter
仍在尝试在流上工作(另外,作者的 using
语句现在正在尝试处置 StreamWriter
,然后它试图关闭流) .
解决此问题的最佳方法是:不要使用
using
,也不要丢弃 StreamReader
和 StreamWriter
。请参阅这个问题。
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());
}
如果您对
sw
和 sr
被垃圾收集而没有在代码中处理(按照建议)感到难过,您可以这样做:
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();
}
自 .net45 起,您可以使用
LeaveOpen
的 StreamWriter
构造函数参数,并且仍然使用 using
语句。示例:
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());
}
}
当您的
using()
的 StreamReader
结束时,它会处理该对象并关闭流,而您的 StreamWriter
仍在尝试使用该流。
当它从 using 语句中退出时,将调用
Dispose
方法,自动关闭流
尝试以下方法:
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());
}
}
问题是这个块:
using (var sr = new StreamReader(ms))
{
Console.WriteLine(sr.ReadToEnd());
}
当
StreamReader
关闭时(离开使用后),它也会关闭其底层流,所以现在 MemoryStream
已关闭。当 StreamWriter
关闭时,它会尝试将所有内容刷新到 MemoryStream
,但它已关闭。
您应该考虑不要将
StreamReader
放入 using 块中。
您必须保持流打开才能读取它。 “StreamWriter”在完成写入后将其关闭
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
}
就我而言(诚然非常神秘,不太可能经常重现),这导致了问题(此代码与使用 iTextSharp 生成 PDF 相关):
PdfPTable tblDuckbilledPlatypi = new PdfPTable(3);
float[] DuckbilledPlatypiRowWidths = new float[] { 42f, 76f };
tblDuckbilledPlatypi.SetWidths(DuckbilledPlatypiRowWidths);
显然,声明 3 单元格/列表,然后仅设置两个宽度值是导致问题的原因。一旦我将“PdfPTable(3)”更改为“PdfPTable(2)”,问题就出在对流烤箱上。
将 MemoryStream 对象更改为 Stream,您可以写入任何文件,因为它不会再被关闭。
StreamstreamIo = new MemoryStream(memoryStream.ToArray());