Reputation: 21364
If I have this:
StreamWriter cout = new StreamWriter("test.txt");
cout.WriteLine("XXX");
// here IOException...
StreamReader cin = new StreamReader("test.txt");
string text = cin.ReadLine();
the clr throws an IOException
because I haven't close the cout
.
In fact If I do this:
StreamWriter cout = new StreamWriter("test.txt");
cout.WriteLine("XXX");
cout.Close();
StreamReader cin = new StreamReader("test.txt");
string text = cin.ReadLine();
I have no exception.
But If I do this and then exit from the application:
StreamReader cin = new StreamReader("test.txt");
string text = cin.ReadLine();
without closing cin
the file can from the OS opened and written.
However reading the source code of StreamReader.cs
I didn't' find a destructor method (i.e. ~StreamReader(...)
). So who does free that file if the garbage collector doesn't invoke Dispose
and there is no finalization method?
Upvotes: 6
Views: 750
Reputation: 106796
StreamReader
and StreamWriter
uses a FileStream
to access the file. FileStream
uses SafeFileHandle
to store the underlying OS file handle. As the SafeFileHandle
class controls an unmanaged resource it correctly has a finalizer (what you call a destructor) that closes the file handle.
But If I do this and then exit from the application: [...] without closing cin the file can from the OS opened and written
When a process terminates all resources used by that process is released to the operating system. It doesn't matter if your application forgot to close a file handle (even though SafeFileHandle
will not "forget"). You will always observe the described behavior no matter how badly written your application is.
I just want to point out that the best way to work with StreamReader
and StreamWriter
and similar classes is using
:
using (StreamWriter cout = new StreamWriter("test.txt")) {
cout.WriteLine("XXX");
}
using (StreamReader cin = new StreamReader("test.txt")) {
string text = cin.ReadLine();
}
This deterministically closes the files when the using
block ends even if an exception is thrown while processing the file.
Upvotes: 3
Reputation: 32192
Internally, the StreamReader
uses a FileStream
:
Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost);
The FileStream
class, being the class that ultimately accesses the file and therefore needs to guarantee cleanup, does have a finalizer, which closes the actual underlying stream. The Dispose
method on the StreamReader
just calls the Close
on the underlying FileStream
.
Upvotes: 5
Reputation: 21380
Operation sytem frees handles and memory owned by application, if the were not freed by application if it closes. Anyway, I'm sure Stream has finalizer.
Upvotes: 0
Reputation: 28499
The operating system has a list which process (application) has what file opened. If your process terminates without explicitly closing the file, the operating system still knows that it is not any longer accessing the file and so can allow other requests to access the file.
Upvotes: 0