9

如果我使用 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();
    }
}
4

7 回答 7

8

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

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

从反光镜...

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);
            }
        }
    }
}
于 2009-11-24T19:02:00.947 回答
6

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

于 2009-11-24T19:02:41.103 回答
6

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

txtFile.Text = File.ReadAllText(@"c:\file.txt");
于 2009-11-24T19:07:06.023 回答
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();
        }
    }
}
于 2009-11-24T19:04:42.457 回答
0

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

于 2009-11-24T19:02:16.813 回答
0

在我看来,总体而言,最好的方法是让 FileStream 仅自行关闭。它并不隐含地知道存在于自身之上的层中的任何内容,因此它执行任何会影响那些更高层的事情实际上是错误的。

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

1)如果它是从现有流创建的,则更高级别的构造应该能够独立于底层流关闭(实际上只是处置它分配给自己使用的任何资源),或者关闭包括底层流。这些应该是两个不同的函数调用,例如 Close() 和 CloseSelf() (如果要以向后兼容现有代码的方式实现)。

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

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

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

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

于 2011-07-11T21:02:30.427 回答
0

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

于 2011-10-27T09:03:27.490 回答