如果我有这个:
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
文件可以从OS打开和写入。
然而,阅读StreamReader.cs
的源代码我没有'找到析构函数方法(即~StreamReader(...)
)。那么,如果垃圾收集器没有调用Dispose
并且没有最终确定方法,谁会释放该文件?
答案 0 :(得分:4)
在内部,StreamReader
uses 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
上的StreamReader
方法仅calls the Close
on the underlying FileStream
。
答案 1 :(得分:3)
StreamReader
和StreamWriter
使用FileStream
来访问该文件。 FileStream
使用SafeFileHandle
来存储底层操作系统文件句柄。由于SafeFileHandle
类控制非托管资源,因此它正确地具有关闭文件句柄的终结器(您称之为析构函数)。
但如果我这样做然后退出应用程序:[...]没有关闭cin文件可以从操作系统打开和写入
当进程终止时,该进程使用的所有资源都将释放到操作系统。如果您的应用程序忘记关闭文件句柄并不重要(即使SafeFileHandle
不会忘记")。无论您的应用程序写得多么糟糕,您都会始终观察所描述的行为。
我只想指出使用StreamReader
和StreamWriter
及类似类的最佳方式是using
:
using (StreamWriter cout = new StreamWriter("test.txt")) {
cout.WriteLine("XXX");
}
using (StreamReader cin = new StreamReader("test.txt")) {
string text = cin.ReadLine();
}
即使在处理文件时抛出异常,这也会在using
块结束时确定性地关闭文件。
答案 2 :(得分:0)
操作系统有一个列表,其中进程(应用程序)具有打开的文件。如果您的进程在没有明确关闭文件的情况下终止,操作系统仍然知道它不再访问该文件,因此可以允许其他请求访问该文件。
答案 3 :(得分:0)
如果应用程序在关闭时没有被应用程序释放,那么操作系统会释放应用程序拥有的句柄和内存。无论如何,我确信Stream有终结器。