内存流 - 无法访问已关闭的流

本文关键字:内存 访问 | 更新日期: 2023-09-27 18:36:26

嗨,为什么using (var sw = new StreamWriter(ms))返回Cannot access a closed Stream exception . Memory 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
}

修复它的最佳方法是什么?谢谢

内存流 - 无法访问已关闭的流

这是因为StreamReader在释放时会自动关闭基础流。using语句会自动执行此操作。

但是,您正在使用的StreamWriter仍在尝试处理流(此外,编写器的using语句现在正在尝试处理StreamWriter,然后尝试关闭流)。

解决此问题的最佳方法是:不要使用using,也不要处理StreamReaderStreamWriter。看到这个问题。

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 开始,您可以使用 StreamWriterLeaveOpen 构造函数参数,并且仍然使用 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());
    }
}

StreamReaderusing()结束时,它会释放对象并关闭流,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 (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 单元格/列表,然后只为宽度设置两个 vals 是导致问题的原因。一旦我将"PdfPTable(3)"更改为"PdfPTable(2)",问题就出在对流烤箱上