MemoryStream - 无法访问关闭的流

问题描述 投票:0回答:8

为什么

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
}
c# asp.net .net streamwriter memorystream
8个回答
151
投票

这是因为

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

47
投票

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

9
投票

当您的

using()
StreamReader
结束时,它会处理该对象并关闭流,而您的
StreamWriter
仍在尝试使用该流。


2
投票

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

1
投票

问题是这个块:

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

StreamReader
关闭时(离开使用后),它也会关闭其底层流,所以现在
MemoryStream
已关闭。当
StreamWriter
关闭时,它会尝试将所有内容刷新到
MemoryStream
,但它已关闭。

您应该考虑不要将

StreamReader
放入 using 块中。


1
投票

您必须保持流打开才能读取它。 “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
}

0
投票

就我而言(诚然非常神秘,不太可能经常重现),这导致了问题(此代码与使用 iTextSharp 生成 PDF 相关):

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

显然,声明 3 单元格/列表,然后仅设置两个宽度值是导致问题的原因。一旦我将“PdfPTable(3)”更改为“PdfPTable(2)”,问题就出在对流烤箱上。


0
投票

将 MemoryStream 对象更改为 Stream,您可以写入任何文件,因为它不会再被关闭。

StreamstreamIo = new MemoryStream(memoryStream.ToArray());

© www.soinside.com 2019 - 2024. All rights reserved.