I'm writing a program that uses text files in C#.
I use a parser class as an interface between the file structure and the program.
This class contains a StreamReader
, a StreamWriter
and a FileStream
. I use the FileStream
as a common stream for the reader and the writer, else these two will conflict when both of them have the file open.
The parser class has a class variable called m_path
, this is the path to the file. I've checked it extensively, and the path is correct. OpenStreams()
and and ResetStreams()
work perfectly, however after calling CloseStreams()
in the delete()
function, the program goes to the catch clause, so File.Delete(m_path)
won't get executed. In other situations the CloseStreams()
function works perfectly. It goes wrong when I'm trying to close the StreamReader (m_writer)
, but it does give an exception (File is Already Closed).
/**
* Function to close the streams.
*/
private void closeStreams() {
if (m_streamOpen) {
m_fs.Close();
m_reader.Close();
m_writer.Close(); // Goes wrong
m_streamOpen = false;
}
}
/**
* Deletes the file.
*/
public int delete() {
try {
closeStreams(); // Catch after this
File.Delete(m_path);
return 0;
}
catch { return -1; }
}
I call the function like this:
parser.delete();
Could anybody give me some tips?
Your File.Delete(m_path);
will never be called, because you get an exception here:
private void closeStreams() {
if (m_streamOpen) {
m_fs.Close();
m_reader.Close();
m_writer.Close(); // throws an exception here
m_streamOpen = false;
}
}
The exception is "Cannot access a closed file"
The cause is explained in the documentation of Close()
in StreamReader
:
Closes the System.IO.StreamReader object and the underlying stream, and releases any system resources associated with the reader.
There are also some articles about this behaviour:
Does disposing streamreader close the stream?
Is there any way to close a StreamWriter without closing its BaseStream?
Can you keep a StreamReader from disposing the underlying stream?
Avoiding dispose of underlying stream
You should consider re-writing your code and use using()
statements.
However, I experimented a bit with your code, and it worked with calling Close()
in other order:
m_writer.Close();
m_reader.Close();
m_fs.Close();
However, I assume that this works only by coincidence (I used .NET 4.0 and probably this will not work in another .NET version). I would strongly advice to not do it in this way.
I tested this:
using (FileStream fs = new FileStream(m_path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
using (StreamReader reader = new StreamReader(fs))
using (StreamWriter writer = new StreamWriter(fs))
{
// so some work here
}
File.Delete(m_path);
But, I know that this may not be for you, since you may want the read and write streams available as fields in your class.
At least, you have some samples to start with ...