关闭文件而不使用

时间:2010-11-29 10:14:38

标签: c# idisposable streamreader streamwriter

我有一个类从一个文件流中读取数据并写入另一个文件流。我担心在closeFiles()处理完成后关闭流。

如何处理一个流的处理可能会引发异常,从而阻止其他流的处理被调用。?

我应该打电话关闭并处理流还是只有一个?

如果我从流处理中捕获任何错误,然后继续移动和删除文件,如lastOperation()中所示,会发生什么?

在一个完美的世界中,我想在c ++样式初始化列表中使用using语句,但我很确定在c#中不可能。

编辑:感谢快速回复的人。那么我应该做的是从IDisposable派生,然后更改构造函数并添加这样的两个处理方法?:

    ~FileProcessor()
    {
        Dispose(true);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    private void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                sw.Flush();
            }
            closeFiles();
            disposed = true;
        }
    }

这基本上就是我正在做的事情:

class FileProcessor
{
    private string in_filename;
    private string out_filename;
    private StreamReader sr;
    private StreamWriter sw;
    bool filesOpen = false;

    public FileProcessor(string filename)
    {
        in_filename = filename; 
        out_filename = filename + ".out";
        openFiles();
    }

    ~FileProcessor()
    {
        closeFiles();
    }

    private void openFiles()
    {
        sr = new StreamReader(in_filename);
        sw = new StreamWriter(out_filename);
        filesOpen = true;
    }

    private void closeFiles()
    {
        if (filesOpen)
        {
            sr.Close();
            sw.Close();
            sr.Dispose();
            sw.Dispose();
            filesOpen = false;
        }
    }

    /* various functions to read, process and write to the files */

    public void lastOperation()
    {
        closeFiles();
        File.Delete( in_filename );
        Directory.Move(out_filename, outdir + out_filename);
    }
}

4 个答案:

答案 0 :(得分:3)

如果您在其中使用IDisposable对象,我认为让您的类实现IDisposable接口是一个好习惯。

然后,您应该确保在Dispose()实现中不抛出异常。如果您处置的每个对象都提供此保证,您的客户将是安全的。

答案 1 :(得分:3)

您的FileProcessor类不应该有析构函数。它没用,但价格昂贵。

它应该有Dispose()(并实现IDisposable接口)来调用closeFiles()。

就像@marcelo回答的那样,Stream.Dispose()不应该抛出。您可以依赖此BCL课程。

但是你应该检查每个Reader / Writer是否为null,以防第一个打开但第二个失败:

if (sr != null) sr.Dispose();
if (sw != null) sw.Dispose();

您的filesOpen无法涵盖两者。

答案 2 :(得分:2)

Dispose方法永远不应该抛出异常。甚至还有一个代码分析工具warning

答案 3 :(得分:0)

在C#中,using确实存在。提供给using语句的对象必须实现IDisposable接口。此接口提供Dispose方法,该方法应释放对象的资源。

如果你的StreamReader和StreamWriter实现了IDisposable,你可以将它们放在一个使用块中,当你完成它们时它们会被彻底处理掉。

using(var sr = new StreamReader(in_filename)) {
    // Perform reader actions
}
// Reader will now be disposed.