Should I be using the using keyword or a dispose method with the following code (since I am opening a stream):
class Program
{
static void Main(string[] args)
{
var x = Deserialize<Dog>(new FileStream(#"C:\Documents and Settings\name\Desktop\demo.xml", FileMode.Open));
}
static T Deserialize<T>(Stream s)
{
XmlSerializer ser = new XmlSerializer(typeof(T));
return (T)ser.Deserialize(s);
}
}
If not, can you please explain why not (does a new FileStream automatically dispose/close the stream)?
You should be using using:
using(var stream = new FileStream(#"C:\path\demo.xml", FileMode.Open))
{
var x = Deserialize<Dog>(stream);
// more code ...
}
Yes you should dispose the stream. If you were to use the File.ReadAllText() for example, this static method would open a stream and dispose it for you. I would suggest a Using, this is because it'll handle exceptions too. For example in this noddy example:
This version correctly disposes the FileStream:
using(FileStream fs = FileStream(path, FileMode.Open))
{
throw new Exception();
}
This example leaks the resources used by the FileStream, you could add try/catch blocks but then it's less readable.
FileStream fs = new FileStream(path, FileMode.Open);
throw new Exception();
fs.Dispose();
If you use using block , he execute in the end of treatment Dispose method.
You use using, because FileStream is non managed object, so Garbage collector don't have informatiosn abouts this object in order to clean, so the developper must clean ressource in order to help your GC.
Link : http://msdn.microsoft.com/fr-fr/library/yh598w02(v=vs.80).aspx
you should use Using with everything that implements IDisposable :)
As already mentioned, you should use using. But why? Well, as already mentioned you should use using for all objects that implements IDisposable.
In your case, FileStream inherits from the Stream object which is implementing IDisposable. Read more about FileStream here: msdn
Related
I'm using the following lines of code in order to write credentials of users to a text file. It's supposed to create the directory inside AppData (which it does) but it doesn't write the credentials to the text file, it leaves it blank!
public void RegisterUserCreds()
{
string[] creds = { Username.Text, Password.Text };
string roaming = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
if (!Directory.Exists(roaming + "/Launcher"))
Directory.CreateDirectory(roaming + "/Launcher");
string specificFolder = roaming + "/Launcher/user_info.txt";
var fs = File.Open(specificFolder, FileMode.OpenOrCreate, FileAccess.ReadWrite);
var sw = new StreamWriter(fs);
sw.WriteLine(Username.Text);
fs.Close();
}
What's the problem? Thanks!
Just use the using statement when operating on streams:
public static void RegisterUserCreds()
{
string[] creds = { Username.Text, Password.Text };
string roaming = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
if (!Directory.Exists(roaming + "/Launcher")) Directory.CreateDirectory(roaming + "/Launcher");
string specificFolder = roaming + "/Launcher/user_info.txt";
using (var fs = File.Open(specificFolder, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var sw = new StreamWriter(fs))
{
sw.WriteLine(Username.Text);
}
}
}
In your code you were closing the file stream before the stream writer was able to flush the changes you want to write so the file was created empty.
You're closing the wrong stream. When you create new stream objects and pass an existing stream to the constructor, that new stream now "owns" the old stream. When you dispose of the newer stream it will automatically dispose of the older one.
In your situation, you're closing the "fs" stream, but the "sw" stream might not have actually written to it yet (it has it's own internal buffer). If you were to close the "sw" stream instead, it would flush it's buffer (into the "fs" stream), and then it would call fs.Dispose() for you to make sure it did the same thing.
There's a much better way, that would help you avoid doing things out-of-order like this, as well as make sure you're calling Dispose() even if exceptions get thrown (streams implement IDisposable, so you're supposed to always call their Dispose() method when you're done with them so they can internally "clean up"). The using statement is perfect for this, since it will call Dispose() even if an exception is thrown (it's a shortcut for wrapping the code with try/finally blocks):
using (var fs = File.Open(specificFolder, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var sw = new StreamWriter(fs))
{
sw.WriteLine(Username.Text);
}
}
This is the same as this:
try
{
var fs = File.Open(specificFolder, FileMode.OpenOrCreate, FileAccess.ReadWrite);
try
{
var sw = new StreamWriter(fs);
sw.WriteLine(Username.Text);
}
finally
{
sw.Dispose();
}
}
finally
{
fs.Dispose();
}
Even though sw.Dispose() will call fs.Dispose() for you, there is no harm in calling fs.Dispose() again. Why is it important to call Dispose()? Let's say an exception was thrown during sw.WriteLine() (e.g. out of disk space, I/O error, etc.)... the file would stay open until your app terminated. The using (or the try/catch version) would make sure the file was closed no matter what.
(side note: with streams, Dispose() and Close() do the same thing, you don't need to call both. Close() just calls Dispose() -- MS included a method called Close() because that was what people were used to with a file API, but the .NET IDisposable interface uses a method called Dispose())
(another side note: starting with .NET 4.5, many of the stream classes have an additional constructor that has a new "leaveOpen" parameter... passing true would tell that stream to NOT dispose of the original stream automatically)
I am using a
FileInfo
class to get the length of the file as follows:
FileInfo infoFile = new FileInfo(#"C:\Text12341234");
long configFileLength = infoFile.Length;
I want to dispose the object created by
FileInfo
class.
I am getting an error that "File has been already in use by another process."
How can i do this?
FileInfo does not implement IDisposable, hence you can't dispose it.
Any results from other methods you call on FileInfo which do implement IDisposable must be dealt with on the actual object, not on FileInfo.
You should use using:
using (FileStream s = File.Create(Application.StartupPath + #"\Client.config.xml"))
{
// your code using s
}
FileInfo doesn't open a stream.If you used methods like OpenRead you need to close the Stream you opened by calling Close method.Or simply wrap your statement with using.
Your code has no problems running, no need to dispose; I think this piece of code will help you:
var f = new FileInfo(#"d:\ntt.txt");
var fs = f.Create();
// you can use dispose here, for it returns filestream
fs.Dispose();
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();
}
How to I dispose the File.OpenRead() correctly. I am currently using the below code?
using (BinaryReader br = new BinaryReader(File.OpenRead(path)))
{
myByte = br.ReadByte();
}
I get the following in Visual Studio when analyzing the code:
Warning 1 CA2000 :
Microsoft.Reliability : In method
'Program.Main(string[])', object
'File.OpenRead(path)' is not disposed
along all exception paths. Call
System.IDisposable.Dispose on object
'File.OpenRead(path)' before all
references to it are out of scope.
At first glance, this looks like a false positive, because disposing the BinaryReader will also dispose the FileStream returned by File.OpenRead:
From: http://msdn.microsoft.com/en-us/library/azy2k2bx.aspx
When the disposing parameter is true, this method releases all resources held by any managed objects that this BinaryReader references. This method invokes the Dispose method of each referenced object.
However, there is one corner case, where the FileStream is really not disposed: When the constructor of BinaryReader throws an exception!
Solution:
The correct way to write your code would be like this:
using (var fs = File.OpenRead(path))
{
BinaryReader br = new BinaryReader(fs);
myByte = br.ReadByte();
}
Background:
BinaryReader only holds a reference to the FileStream and therefore doesn't need to be disposed.
Code Analysis shares this opinion.
BTW: When using this solution for a writable stream, it is important to flush the writer before the stream is disposed:
using (var fileStream = new FileStream(...))
{
var writer = new StreamWriter(fileStream);
writer.WriteLine(...);
writer.Flush(); // <-- Important
}
If you forget this, your stream might not contain everything that has been written using the StreamWriter.
Hows about:
using (Filestream fs = File.OpenRead(Path))
{
using (BinaryReader br = new BinaryReader(fs))
{
myByte = br.ReadByte();
}
}
File.OpenRead returns a FileStream, which is also IDisposible. You can put it in an outer using block if you like, or declare it and dispose it outside your current using.
Both the FileStream that's created by File.OpenRead and the BinaryReader that you create on that FileStream need to be disposed of, so you need an explicit reference to each:
using(FileStream fs = File.OpenRead(path))
using(BinaryReader br = new BinaryReader(fs))
{
myByte = br.ReadByte();
}