How to dispose an object created by class FileInfo? - c#

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();

Related

Writing to a text file in AppData doesn't work - C#

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)

Having some trouble to delete a file using FileStreams in C#

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 ...
File.Delete should work, either you didn't call your delete method, or m_path is an invalid path

"The process cannot access the file because it is being used by another process" with Images

I've seen many issues like this that have been solved and the problem was mostly due to streams not being disposed of properly.
My issue is slightly different, here follow a code snippet
foreach (Images item in ListOfImages)
{
newPath = Path.Combine(newPath, item.ImageName + item.ImageExtension);
File.Create(newPath);
File.WriteAllBytes(newPath, item.File);
}
Where Images is a custom struct and item.File is the raw data, byte[].
My issue is that at the line where the WriteAllBytes is called, an exception is thrown. The message reads:
The process cannot access the file because it is being used by another process
Again I have no clue how am I going to somehow close the process.
Since File.Create returns the stream i would dispose it properly:
using(var stream = File.Create(newPath)){}
File.WriteAllBytes(newPath, item.File);
or you can use the stream to write to the file directly:
using (FileStream fs = File.Create(newPath))
{
fs.Write(item.File, 0, item.File.Length);
}
or, probably the easiest, use File.WriteAllBytes alone:
File.WriteAllBytes(newPath, item.File);
Creates a new file, writes the specified byte array to the file, and
then closes the file. If the target file already exists, it is
overwritten.
You state that your problem has nothing to do with disposing streams but check this MSDN article:
http://msdn.microsoft.com/en-us/library/d62kzs03.aspx
What does File.Create return? A FileStream!!!!
And, at the end of the day, why are you using File.Create if File.WriteAllBytes creates a file if this doesn't exist? ;)
Creates a new file, writes the specified byte array to the file, and
then closes the file. If the target file already exists, it is
overwritten.
Check it on MSDN too: http://msdn.microsoft.com/en-us/library/system.io.file.writeallbytes.aspx
using (FileStream fs =
new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
Your log may be write locked, so try with FileShare.ReadWrite.
The create method opens the file for writing and returns a FileStream object for you to work with. Just because you are not referencing it does not mean it does not need to be returned.
foreach (Images item in ListOfImages)
{
newPath = Path.Combine(newPath, item.ImageName + item.ImageExtension);
FileStream f = File.Create(newPath);
f.Write(item.File, 0, item.File.Length);
}
The File.WriteAllBytes creates the file if necessary. You can juts use:
foreach (Images item in ListOfImages)
{
newPath = Path.Combine(newPath, item.ImageName + item.ImageExtension);
File.WriteAllBytes(newPath, item.File);
}
And are you combine path correctly?
This is the most specific way to accomplish what you are trying to do:
foreach (Images item in ListOfImages)
{
using (System.IO.FileStream output = new System.IO.FileStream(Path.Combine(newPath, item.ImageName + item.ImageExtension),
System.IO.FileMode.Create, System.IO.FileAccess.Write))
{
output.Write(item.File, 0, item.File.Length);
output.Flush();
output.Close();
}
}
You also need to fix your logic for creating the path, which I have done in my example above. You were concatenating the newPath over and over again.
Force the garbage collector to clean.
GC.Collect();

C# Using keywords with streams

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

Create a temporary file from stream object in c#

Given a stream object which contains an xlsx file, I want to save it as a temporary file and delete it when not using the file anymore.
I thought of creating a class that implementing IDisposable and using it with the using code block in order to delete the temp file at the end.
Any idea of how to save the stream to a temp file and delete it on the end of use?
Thanks
You could use the TempFileCollection class:
using (var tempFiles = new TempFileCollection())
{
string file = tempFiles.AddExtension("xlsx");
// do something with the file here
}
What's nice about this is that even if an exception is thrown the temporary file is guaranteed to be removed thanks to the using block. By default this will generate the file into the temporary folder configured on the system but you could also specify a custom folder when invoking the TempFileCollection constructor.
You can get a temporary file name with Path.GetTempFileName(), create a FileStream to write to it and use Stream.CopyTo to copy all data from your input stream into the text file:
var stream = /* your stream */
var fileName = Path.GetTempFileName();
try
{
using (FileStream fs = File.OpenWrite(fileName))
{
stream.CopyTo(fs);
}
// Do whatever you want with the file here
}
finally
{
File.Delete(fileName);
}
Another approach here would be:
string fileName = "file.xslx";
int bufferSize = 4096;
var fileStream = System.IO.File.Create(fileName, bufferSize, System.IO.FileOptions.DeleteOnClose)
// now use that fileStream to save the xslx stream
This way the file will get removed after closing.
Edit:
If you don't need the stream to live too long (eg: only a single write operation or a single loop to write...), you can, as suggested, wrap this stream into a using block. With that you won't have to dispose it manually.
Code would be like:
string fileName = "file.xslx";
int bufferSize = 4096;
using(var fileStream = System.IO.File.Create(fileName, bufferSize, System.IO.FileOptions.DeleteOnClose))
{
// now use that fileStream to save the xslx stream
}
// Get a random temporary file name w/ path:
string tempFile = Path.GetTempFileName();
// Open a FileStream to write to the file:
using (Stream fileStream = File.OpenWrite(tempFile)) { ... }
// Delete the file when you're done:
File.Delete(tempFile);
EDIT:
Sorry, maybe it's just me, but I could have sworn that when you initially posted the question you didn't have all that detail about a class implementing IDisposable, etc... anyways, I'm not really sure what you're asking in your (edited?) question. But this question: Any idea of how to save the stream to temp file and delete it on the end of use? is pretty straight-forward. Any number of google results will come back for ".NET C# Stream to File" or such.
I just suggest for creating file use Path.GetTempFileName(). but others depends on your usage senario, for example if you want to create it in your temp creator class and use it just there, it's good to use using keyword.

Categories