I have 2 pieces of code.
Take a look at this one.
static void Main(string[] args)
{
using (FileStream fs = new FileStream("temp.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (StreamWriter writer = new StreamWriter(fs))
{
writer.WriteLine("Hello World");
using (StreamReader reader = new StreamReader(fs))
{
Console.WriteLine(reader.ReadToEnd());
} // Line-1
} //Line-2 -> System.ObjectDisposedException: 'Cannot access a closed file.'
}
}
At the Line-2 I get System.ObjectDisposedException occurs.
Why do I get this exception here?
After a little bit of thinking I thought that the exception occurred at Line-2 because the Stream associated with reference 'fs' is already closed at Line-1. And at Line-2 it is trying to close the same stream again. And this answer made sense. Hence, I thought I had found the right answer to my question but then I tried something a little bit different.
Now look at this piece of code.
static void Main(string[] args)
{
using (FileStream fs = new FileStream("temp.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (StreamReader reader = new StreamReader(fs))
{
Console.WriteLine(reader.ReadToEnd());
using (StreamWriter writer = new StreamWriter(fs))
{
writer.WriteLine("Hello World");
} // Line-1
} // Line-2 -> No Exception occurred.
}
}
In this piece of code I didn't get any exception. Even though I am doing the same thing again. Here also the stream associated with reference 'fs' is already closed at Line-1 and it is also trying to close the stream at Line-2.
So why didn't I get any exception here?
My question is different from this Is there any way to close a StreamWriter without closing its BaseStream? because I am trying to do the same thing with the second code and despite the fact (in second code) that using statement already closed the base stream (fs) in Line-1. I still don't get any exception in Line-2.
Since #mjwills and #evk said the exception occurred because of flushing the contents of the stream after the file had been closed.
I tried this.
static void Main(string[] args)
{
using (FileStream fs = new FileStream("temp.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (StreamWriter writer = new StreamWriter(fs))
{
writer.WriteLine("Hello World");
writer.Flush(); // Flushed the contents explicitly.
using (StreamReader reader = new StreamReader(fs))
{
Console.WriteLine(reader.ReadToEnd());
} // Line-1
} // Line-2 -> System.ObjectDisposedException: 'Cannot access a closed file.'
}
}
And the result is same I still have that exception even though I have explicitly flushed the contents. Please help.
StreamWriter's Dispose method flushes to disk.
StreamReader's Dispose method does not (why would it? it is just a reader...).
As such, it is "kind of" safe to dispose the writer then the reader (in the sense that it works), but not vice versa.
Consider using leaveOpen on your StreamWriter and StreamReader to avoid this class of problem. By using leaveOpen, you are then able to manually Dispose the Stream which means you can be 100% confident the code will work - and not have to concern yourself with flushing behaviour etc etc.
Related
The new Visual Studio 2012 is complaining about a common code combination I have always used. I know it seems like overkill but I have done the following in my code 'just to be sure'.
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var sr = new StreamReader(fs))
{
// Code here
}
}
Visual studio is 'warning' me that I am disposing of fs more than once. So my question is this, would the proper way to write this be:
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
var sr = new StreamReader(fs);
// do stuff here
}
Or should I do it this way (or some other variant not mentioned).
var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (var sr = new StreamReader(fs))
{
// Code here
}
I searched several questions in StackOverflow but did not find something that addressed the best practice for this combination directly.
Thank you!
The following is how Microsoft recommends doing it. It is long and bulky, but safe:
FileStream fs = null;
try
{
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (TextReader tr= new StreamReader(fs))
{
fs = null;
// Code here
}
}
finally
{
if (fs != null)
fs.Dispose();
}
This method will always ensure that everything is disposed that should be despite what exceptions may be thrown. For example, if the StreamReader constructor throws an exception, the FileStream would still be properly disposed.
Visual studio is 'warning' me that I am disposing of fs more than once.
You are, but that is fine. The documentation for IDisposable.Dispose reads:
If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times.
Based on that, the warning is bogus, and my choice would be to leave the code as it is, and suppress the warning.
As Dan's answer only appears to work with StreamWriter, I believe this might be the most acceptable answer.
(Dan's answer will still give the disposed twice warning with StreamReader - as Daniel Hilgarth and exacerbatedexpert mentions, StreamReader disposes the filestream)
using (TextReader tr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
string line;
while ((line = tr.ReadLine()) != null)
{
// Do work here
}
}
This is very similar to Daniel Hilgarth's answer, modified to call dispose via the Using statement on StreamReader as it is now clear StreamReader will call dispose on FileStream (According to all the other posts, documentation referenced)
Update:
I found this post. For what it is worth.
Does disposing streamreader close the stream?
Yes, the correct way would be to use your first alternative:
using (FileStream fs = new FileStream(filePath, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite))
{
TextReader tr = new StreamReader(fs);
// do stuff here
}
The reason is the following:
Disposing the StreamReader only disposes the FileStream so that's actually the only thing you need to dispose.
Your second option (just the inner "using") is no solution as it would leave the FileStream undisposed if there was an exception inside the constructor of the StreamReader.
It's because the way you used StreamReader disposes the stream when it is disposed. So, if you dispose the stream too, it's being disposed twice. Some consider this a flaw in StreamReader--but it's there none-the-less. In VS 2012 (.NET 4.5) there is an option in StreamReader to not dispose of the stream, with a new constructor: http://msdn.microsoft.com/en-us/library/gg712952
Two solutions:
A) You trust Reflector or Documentation and you know *Reader and *Writer will close the underlying *Stream. But warning: it won't work in case of a thrown Exception. So it is not the recommended way:
using (TextReader tr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
// Code here
}
B) You ignore the warning as documentation states The object must not throw an exception if its Dispose method is called multiple times. It's the recommended way, as it's both a good practice to always use using, and safe in case of a thrown Exception:
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
internal void myMethod()
{
[...]
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (TextReader tr = new StreamReader(fs))
{
// Code here
}
}
Given all the nonsense this (perfectly legitimate!) question generated, this would be my preference:
FileStream fs = null;
TextReader tr= null;
try
{
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
tr= new StreamReader(fs);
// Code here
}
finally
{
if (tr != null)
tr.Dispose();
if (fs != null)
fs.Dispose();
}
The links below illustrate perfectly legal syntax. IMO, this "using" syntax is far preferable to nested "using". But I admit - it does not solve the original question:
http://blogs.msdn.com/b/ericgu/archive/2004/08/05/209267.aspx
.NET - Replacing nested using statements with single using statement
IMHO...
I have been looking at writing a string into a file and then read it line by line, but I always get the error IOException: Sharing violation on path C:...\level1.txt. I looked on the internet and they said I should use the same stream to write and read but it didn't work,so I tried to make a different stream for each one and it didn't work either.
FileStream F = new FileStream("level1.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(F);
sw.Write(Gui.codeText.Replace("\n", "\r\n"));
F.Close();
FileStream F2 = new FileStream("level1.txt", FileMode.Open, FileAccess.Read);
StreamReader file = new StreamReader(F2);
while ((line = file.ReadLine()) != null)
{ ....}
I think you just need to use the Using statement while read and write.
Since the StreamWriter and StreamReader classes inherits Stream, which is implements the IDisposable interface, the example can use using statements to ensure that the underlying file is properly closed following the write or read operations.
using (StreamWriter sw = new StreamWriter(F))
{
//Write Logic goes here...
}
using (StreamReader file = new StreamReader(F2))
{
//Read Logc goes here...
}
The Using Statement:
An using statement is translated into three parts: acquisition, usage,
and disposal. Usage of the resource is implicitly enclosed in a try
statement that includes a finally clause. This finally clause disposes
of the resource. If a null resource is acquired, then no call to
Dispose is made, and no exception is thrown.
On this code:
public static string Base64FromFileName(string fileName)
{
try
{
FileInfo fInfo = new FileInfo(fileName);
long numBytes = fInfo.Length;
FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fStream);
byte[] bdata = br.ReadBytes((int)numBytes);
br.Close();
fStream.Close();
return Convert.ToBase64String(bdata);
}
catch(Exception e)
{
throw e;
}
}
...I get, courtesy of Visual Studio's Code Analysis tool, the warning, "Do not dispose objects multiple times...To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object" on the "fStream.Close();" line.
Why? Is fStream disposed in the line above, where the BinaryReader is closed?
Wouldn't I be better off refactoring it like this anyway:
. . .
using (FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(fStream))
{
byte[] bdata = br.ReadBytes((int)numBytes);
} //br.Close();
} //fStream.Close();
. . .
?
BinaryReader.Close also closes the underlying stream, so this would indeed cause the stream to be disposed of twice. But that's not a real problem, disposing twice doesn't hurt.
You could write this much better as
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
using (var br = new BinaryReader(fs, new UTF8Encoding(), true))
{
return Convert.ToBase64String(br.ReadBytes((int)numBytes));
}
This is the bomb-proof version:
Anything that is successfully constructed is guaranteed to be disposed
You won't dispose of the stream twice because the boolean leaveOpen argument on the BinaryReader constructor ensures that disposing (closing) it won't also close the stream
Code Analysis is right; Code Analysis is wrong.
Yes, you're closing the FileStream twice. This is harmless. So is disposing it twice. Multiple disposal happens. It is the responsibility of the developer of a disposable component to handle multiple disposal properly and without throwing exceptions1.
However, while calling Dispose() on a disposed FileStream is a no-op by convention, the same isn't true of your code, which calls Close() on a disposed stream. Don't do that.
Your suggested fix with the nested using is fine.
1 The contract for IDisposable.Dispose requires:
If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times. Instance methods other than Dispose can throw an ObjectDisposedException when resources are already disposed.
The formal term for this behavior is idempotence.
Is there any chance that fileStream object will likely be destroyed before its call to the Close method as below?
FileStream fileStream = new FileStream(xxx);
StreamReader txtReader = new StreamReader(fileStream);
curLog = txtReader.ReadToEnd();
txtReader.Close();
fileStream.Close();
Is there any chance that fileStream object will likely be destroyed
before its call to the Close method as below?
No.
But you should never write code like that. You should always wrap IDisposable resources in using statements to ensure that they will be disposed even if an exception is thrown and that you won't be leaking handles.
using (FileStream fileStream = new FileStream(xxx))
using (StreamReader txtReader = new StreamReader(fileStream))
{
curLog = txtReader.ReadToEnd();
}
But for the purpose of this specific example you could simply use the ReadAllText method.
string curLog = File.ReadAllText(xxx);
No, there isn't any chance that it is closed before that. And i would recommend using it like this
FileStream fileStream = new FileStream(xxx);
using (StreamReader txtReader = new StreamReader(fileStream))
{
curLog = txtReader.ReadToEnd();
}
The new Visual Studio 2012 is complaining about a common code combination I have always used. I know it seems like overkill but I have done the following in my code 'just to be sure'.
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var sr = new StreamReader(fs))
{
// Code here
}
}
Visual studio is 'warning' me that I am disposing of fs more than once. So my question is this, would the proper way to write this be:
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
var sr = new StreamReader(fs);
// do stuff here
}
Or should I do it this way (or some other variant not mentioned).
var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (var sr = new StreamReader(fs))
{
// Code here
}
I searched several questions in StackOverflow but did not find something that addressed the best practice for this combination directly.
Thank you!
The following is how Microsoft recommends doing it. It is long and bulky, but safe:
FileStream fs = null;
try
{
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (TextReader tr= new StreamReader(fs))
{
fs = null;
// Code here
}
}
finally
{
if (fs != null)
fs.Dispose();
}
This method will always ensure that everything is disposed that should be despite what exceptions may be thrown. For example, if the StreamReader constructor throws an exception, the FileStream would still be properly disposed.
Visual studio is 'warning' me that I am disposing of fs more than once.
You are, but that is fine. The documentation for IDisposable.Dispose reads:
If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times.
Based on that, the warning is bogus, and my choice would be to leave the code as it is, and suppress the warning.
As Dan's answer only appears to work with StreamWriter, I believe this might be the most acceptable answer.
(Dan's answer will still give the disposed twice warning with StreamReader - as Daniel Hilgarth and exacerbatedexpert mentions, StreamReader disposes the filestream)
using (TextReader tr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
string line;
while ((line = tr.ReadLine()) != null)
{
// Do work here
}
}
This is very similar to Daniel Hilgarth's answer, modified to call dispose via the Using statement on StreamReader as it is now clear StreamReader will call dispose on FileStream (According to all the other posts, documentation referenced)
Update:
I found this post. For what it is worth.
Does disposing streamreader close the stream?
Yes, the correct way would be to use your first alternative:
using (FileStream fs = new FileStream(filePath, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite))
{
TextReader tr = new StreamReader(fs);
// do stuff here
}
The reason is the following:
Disposing the StreamReader only disposes the FileStream so that's actually the only thing you need to dispose.
Your second option (just the inner "using") is no solution as it would leave the FileStream undisposed if there was an exception inside the constructor of the StreamReader.
It's because the way you used StreamReader disposes the stream when it is disposed. So, if you dispose the stream too, it's being disposed twice. Some consider this a flaw in StreamReader--but it's there none-the-less. In VS 2012 (.NET 4.5) there is an option in StreamReader to not dispose of the stream, with a new constructor: http://msdn.microsoft.com/en-us/library/gg712952
Two solutions:
A) You trust Reflector or Documentation and you know *Reader and *Writer will close the underlying *Stream. But warning: it won't work in case of a thrown Exception. So it is not the recommended way:
using (TextReader tr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
// Code here
}
B) You ignore the warning as documentation states The object must not throw an exception if its Dispose method is called multiple times. It's the recommended way, as it's both a good practice to always use using, and safe in case of a thrown Exception:
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
internal void myMethod()
{
[...]
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (TextReader tr = new StreamReader(fs))
{
// Code here
}
}
Given all the nonsense this (perfectly legitimate!) question generated, this would be my preference:
FileStream fs = null;
TextReader tr= null;
try
{
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
tr= new StreamReader(fs);
// Code here
}
finally
{
if (tr != null)
tr.Dispose();
if (fs != null)
fs.Dispose();
}
The links below illustrate perfectly legal syntax. IMO, this "using" syntax is far preferable to nested "using". But I admit - it does not solve the original question:
http://blogs.msdn.com/b/ericgu/archive/2004/08/05/209267.aspx
.NET - Replacing nested using statements with single using statement
IMHO...