关闭FileStream会关闭StreamReader吗?

时间:2009-11-24 19:00:16

标签: c# .net-3.5 filestream streamreader

如果我使用FileStream创建StreamReader,关闭FileStream时StreamReader会关闭还是我还需要关闭StreamReader?

public void ReadFile()
{
    var file = new FileStream("c:\file.txt", FileMode.Open, FileAccess.Read);
    var reader = new StreamReader(file);

    try
    {
        txtFile.Text = reader.ReadToEnd();
    }
    catch (Exception)
    {
        throw;
    }
    finally
    {
        file.Close();
    }
}

7 个答案:

答案 0 :(得分:7)

基本上是的。您实际上不必关闭StreamReader。如果这样做,它只会关闭基础流。

@Bruno对关闭最外层包装器提出了一个很好的观点。最好关闭最外层的流并让它关闭底层流,以确保正确释放所有资源。

来自Reflector ...

public class StreamReader : TextReader
{
    public override void Close()
    {
        this.Dispose(true);
    }

    protected override void Dispose(bool disposing)
    {
        try
        {
            if ((this.Closable && disposing) && (this.stream != null))
            {
                this.stream.Close();
            }
        }
        finally
        {
            if (this.Closable && (this.stream != null))
            {
                this.stream = null;
                this.encoding = null;
                this.decoder = null;
                this.byteBuffer = null;
                this.charBuffer = null;
                this.charPos = 0;
                this.charLen = 0;
                base.Dispose(disposing);
            }
        }
    }
}

答案 1 :(得分:6)

没有。您应该关闭reader。在实践中,这可能不会出现任何问题,但StreamReader可能会增加一些可能需要清理的开销。所以你应该总是关闭最顶层的包装器。

答案 2 :(得分:6)

您也可以使用File.ReadAllText方法:

txtFile.Text = File.ReadAllText(@"c:\file.txt");

答案 3 :(得分:2)

您不需要关闭StreamReader,因为它不拥有任何非托管资源。关闭FileStream就足够了。您可以使用using重写代码,如下所示:

public void ReadFile()
{
    using (var file = new FileStream("c:\file.txt", FileMode.Open, FileAccess.Read))
    {
        txtFile.Text = new StreamReader(file).ReadToEnd();
    }
}

一般情况下,如果您有疑问,最好是安全并在使用完毕后处理所有IDisposable对象。

public void ReadFile()
{
    using (FileStream file = new FileStream("c:\file.txt", FileMode.Open, FileAccess.Read))
    {
        using (StreamReader streamReader = new StreamReader(file))
        {
            txtFile.Text = streamReader.ReadToEnd();
        }
    }
}

答案 4 :(得分:0)

没有。最好的办法是以打开它们的相反顺序关闭它们。

答案 5 :(得分:0)

在我看来,整体做到这一点的最好方法是让FileStream只关闭它自己。它并不隐含地知道自身上面存在的任何事物,因此它做任何会影响那些更高层的事情实际上是错误的。

话虽如此,更高级别的构造不应该公理地假设任何提供的底层图层,或者如果他们这样做,他们应该明确地这样做:

1)如果它是从现有流创建的,那么更高级别的构造应该能够关闭基础流的 INDEPENDENTLY (实际上只是处理它为自己分配的任何资源)使用),或关闭包含基础流。这些应该是两个不同的函数调用,例如Close()和CloseSelf()(如果要以与现有代码向后兼容的方式实现)。

2)如果它不是从现有流创建的(也就是说,构造函数必须创建底层流),那么关闭更高级别的构造也应该强制关闭基础流,因为在这种情况下底层流是高级构造的隐式部分。在这种情况下,CloseSelf()只需调用Close()。

以完成它的方式实现这些类似乎很浪费。如果您计划使用相同的文件(作为示例)串行输入和串行输出,如果您希望获得对后代类的更高级功能的访问,系统会强制您将其视为两个不同的实体。您可以选择坚持较低级别的构造并自己实现更高级别的功能 - 有效地重新实现您已经存在的特殊版本的后代类。

如果按上述方式完成,典型功能将像现在一样简单实现,但对于更复杂的应用程序,可以保留在文件上放置单个锁并根据需要重新使用它的功能。在需要时,而不是必须放弃锁和所有相关资源,然后立即重新分配它们 - 在没有任何正当理由的情况下将开销和内存碎片添加到系统中。

但在现有条件下,正确的事情是明确的。不能假定FileStream知道它成为其中任何对象的任何内容,因此您必须关闭最外层的封闭构造。无论是否有任何方式,这都适用,正如Bruno等人所指出的那样,并且由于它们给出的原因 - 兼容性。假设是最丑陋的虫子的曾祖父。

答案 6 :(得分:0)

有趣的是,关闭StreamReader或writer会影响拥有的FileStream的读/写状态。这似乎意味着您不能使用StreamReader,然后使用相同的文件流使用StreamWriter。