【问题标题】:Finalization on StreamWriter and StreamReaderStreamWriter 和 StreamReader 的最终确定
【发布时间】:2016-08-23 01:17:22
【问题描述】:

如果我有这个:

StreamWriter cout = new StreamWriter("test.txt");
cout.WriteLine("XXX");

// here IOException...
StreamReader cin = new StreamReader("test.txt");
string text = cin.ReadLine();

clr 抛出一个IOException,因为我还没有关闭cout

事实上,如果我这样做:

StreamWriter cout = new StreamWriter("test.txt");
cout.WriteLine("XXX");

cout.Close();

StreamReader cin = new StreamReader("test.txt");
string text = cin.ReadLine();

我也不例外。

但是如果我这样做然后退出应用程序:

StreamReader cin = new StreamReader("test.txt");
string text = cin.ReadLine();

不关闭cin 文件可以从操作系统打开和写入。

但是阅读StreamReader.cs的源代码我没有找到析构方法(即~StreamReader(...))。那么如果垃圾收集器没有调用Dispose 并且没有终结方法,谁来释放该文件?

【问题讨论】:

  • StreamReader 使用 FileShare.Read 创建一个 FileStream 拒绝任何人写入该文件,保证在您阅读时文件不会更改。好的。但这行不通,StreamWriter 要求 FileAccess.Write 并得到它。因此,您将被拒绝访问,因为操作系统不再保证文件不会更改。如果您想放弃该保证,请使用 FileStream 通过 FileShare.ReadWrite 打开文件并将其传递给 StreamReader 构造函数。

标签: c#


【解决方案1】:

在内部,StreamReaderuses a FileStream

 Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost);

FileStream 类是最终访问文件的类,因此需要保证清理,does have a finalizer,它会关闭实际的底层流。 Dispose 上的 Dispose 方法只是 calls the Close on the underlying FileStream

【讨论】:

    【解决方案2】:

    StreamReaderStreamWriter 使用 FileStream 访问文件。 FileStream 使用SafeFileHandle 来存储底层操作系统文件句柄。由于SafeFileHandle 类控制一个非托管资源,它正确地有一个终结器(你称之为析构函数)来关闭文件句柄。

    但是如果我这样做然后退出应用程序:[...] 不关闭 cin 文件可以从操作系统打开和写入

    当一个进程终止时,该进程使用的所有资源都会释放给操作系统。如果您的应用程序忘记关闭文件句柄也没关系(即使SafeFileHandle 不会“忘记”)。无论您的应用程序写得多么糟糕,您都将始终观察到所描述的行为。

    我只想指出,使用 StreamReaderStreamWriter 以及类似课程的最佳方式是 using

    using (StreamWriter cout = new StreamWriter("test.txt")) {
      cout.WriteLine("XXX");
    }
    
    using (StreamReader cin = new StreamReader("test.txt")) {
      string text = cin.ReadLine();
    }
    

    这会在 using 块结束时确定性地关闭文件,即使在处理文件时抛出异常也是如此。

    【讨论】:

      【解决方案3】:

      操作系统有一个列表,哪个进程(应用程序)打开了哪个文件。如果您的进程在没有明确关闭文件的情况下终止,操作系统仍然知道它不再访问该文件,因此可以允许其他请求访问该文件。

      【讨论】:

        【解决方案4】:

        操作系统释放应用程序拥有的句柄和内存,如果应用程序关闭时没有释放它们。无论如何,我确信 Stream 有终结器。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-12-17
          • 1970-01-01
          • 2012-02-22
          • 1970-01-01
          • 1970-01-01
          • 2014-05-22
          • 2019-02-26
          • 1970-01-01
          相关资源
          最近更新 更多