Using method: System.IO.File.Create()
After the file gets created, it still remains used by a process, and I can't delete it.
Any idea how I can better create the file, should be a 0byte file, and then somehow close and dispose?
JL,
You should wrap your call to .Create in a using statement so that the FileStream that .Create returns will be closed properly. IE:
using (File.Create("path")){...}
The Create method not only creates the file, it opens it and return a FileStream object that you can use to write to the file.
You have to close the file after yourself, otherwise it will not be closed before the garbage collector cleans up the FileStream object.
The easiest way is to simply close the file using the reference that the Create method returns:
File.Create(fileName).Close();
nikmd23 has the short answer, the long answer is: the FileStream that File.Create(...) is returning is not being deterministically disposed of, therefore it's file handle is not closed when you're trying to delete it.
As nikmd23 put it, wrapping your File.Create(...) call will with a using statement will make sure the stream is closed and disposed of:
using (FileStream fs = File.Create(path)) {
// do anything with the stream if need-be...
}
File.Delete(path); //after it's been disposed of.
The using(...) block is really just compiler-sugar for:
FileStream fs = File.Create(path);
try {
// do anything with the stream if need-be...
}
finally {
fs.Dispose();
}
File.Delete(path)
You should use nikmd23's answer in almost all cases. If you can't, because you need to pass the FileStream somewhere else, make sure to call the FileStream.Close method eventually. Preferably you would have the class that 'owns' the FileStream implement IDisposable itself, and close the stream in its Dispose method.
For more information on implementing IDisposable, refer to the MSDN documentation. Easier reading, and more up to date, is Joe Duffy's post on the subject.
using(FileStream f = File.Create(file_path))
{
// ... do something with file
f.Close();
}
The "f.Close();" line closing file immediately. If not close manually, Disposing may not close it.
See System.IO.File.Create(String) Method paramter and return value description
Parameters
path
Type: System.String
The path and name of the file to create.
Return Value
Type: System.IO.FileStream
A FileStream that provides read/write access to the file specified in path.
The FileStream return value is there for IO access to the created file. If you are not interested in writing (or reading) the newly created file, close the stream. That is what the using block is ensuring.
Related
I cannot understand why I need to dispose the File.Create or wrap the creation within a using station before accessing the file and write to it. Why do I need to dispose that instances of Stream class that File.Create initialized, and have to create another Stream instance to write to it? Are they on a different thread, why?
Why can't creation, text-writing, and deletion share the same Stream? Perhaps I just do not understand Stream.
For example:
File.Create(...);
File.ReadLine(...); <-- The process cannot access the file ... because it is being used by another process
using (File.Create(...)) {};
File.ReadLine(...); <-- OK
See the Remarks section on the File.Create page on MSDN (emphasis mine):
The FileStream object created by this method has a default FileShare
value of None; no other process or code can access the created file
until the original file handle is closed.
I am reading, then writing to a text file. I do this in multiple parts of my program. After I'm done writing, I always close it (I use streamreader/writer). There is usually about 3 seconds between the close and the next time it's opened.
However, the second time I need to write to the same file, I always get an access denied error because another process is using it. At no point is any other process ever using it, and restarting my program lets me read from it.
This is the open/write/close code:
System.IO.StreamWriter file = new System.IO.StreamWriter(saveFileLocation.Text);
file.WriteLine(account);
file.Close();
Assuming there is no multi-threading then the issue is with proper disposal. The correct way to dispose of a stream or in general types that implement IDisposable is to wrap them in a using statement. The using statement ensures proper disposal and uses a finally block to ensure that the stream is closed even in exceptional circumstances.
using(var file = new System.IO.StreamWriter(saveFileLocation.Text))
{
//do work...
file.WriteLine(account);
}//when file goes out of scope it will close
Do this for all your streams.
use using statement or try{ }finally{ file.Close(); }
Are you sure an exception isn't being thrown, preventing close from being called? Either way this is better code:
using (System.IO.StreamWriter file = new System.IO.StreamWriter(saveFileLocation.Text))
{
file.WriteLine(account);
}
I ran into something interesting when using a StreamWriter with a FileStream to append text to an existing file in .NET 4.5 (haven't tried any older frameworks). I tried two ways, one worked and one didn't. I'm wondering what the difference between the two is.
Both methods contained the following code at the top
if (!File.Exists(filepath))
using (File.Create(filepath));
I have the creation in a using statement because I've found through personal experience that it's the best way to ensure that the application fully closes the file.
Non-Working Method:
using (FileStream f = new FileStream(filepath, FileMode.Append,FileAccess.Write))
(new StreamWriter(f)).WriteLine("somestring");
With this method nothing ends up being appended to the file.
Working Method:
using (FileStream f = new FileStream(filepath, FileMode.Append,FileAccess.Write))
using (StreamWriter s = new StreamWriter(f))
s.WriteLine("somestring");
I've done a bit of Googling, without quite knowing what to search for, and haven't found anything informative. So, why is it that the anonymous StreamWriter fails where the (non-anonymous? named?) StreamWriter works?
It sounds like you did not flush the stream.
http://msdn.microsoft.com/en-us/library/system.io.stream.flush.aspx
It looks like StreamWriter writes to a buffer before writing to the final destination, in this case, the file. You may also be able to set the AutoFlush property and not have to explicitly flush it.
http://msdn.microsoft.com/en-us/library/system.io.streamwriter.autoflush.aspx
To answer your question, when you use the "using" block, it calls dispose on the StreamWriter, which must in turn call Flush.
The difference between the two code snippets is the use of using. The using statement disposes the object at the end of the block.
A StreamWriter buffers data before writing it to the underlying stream. Disposing the StreamWriter flushes the buffer. If you don't flush the buffer, nothing gets written.
From MSDN:
You must call Close to ensure that all data is correctly written out to the underlying stream.
See also: When should I use “using” blocks in C#?
I have a function that is reading a file and adding some of the string in a list and returning this list. Because I wanted that nobody and nothing could change, delete or whatever the current file that I was reading I locked it. Everything was fine, I did it somehow like this:
public static List<string> Read(string myfile)
{
using (FileStream fs = File.Open(myfile, FileMode.Open, FileAccess.Read, FileShare.None))
{
//read lines, add string to a list
//return list
}
}
Thats fine. Now I have another function in another class that is doing stuff with the list and calling other functions and so on. Now sometimes I want to move the file that I was reading. And here is the problem: because Im now in a new function and the function Read(string myfile) is already processed, there is no more lock in the file.
//in another class
public static void DoStuff(/*somefile*/)
{
List<string> = Read(/*somefile*/);
//the file (somefile) is not more locked!
//do stuff
if (something)
Move(/*somefile*/) //could get an error, file maybe not more there or changed...
}
So another function/user could change the file, rename it, deleting it or whatever => Im not able to move this file. Or I will move the changed file, but I dont what that. If I would use threading, another thread with the same function could lock the file again and I could not move it.
Thats why I somehow need to lock this file for a longer time. Is there an easy way? Or do I have to replace my using (FileStream fs = File.Open(myfile, FileMode.Open, FileAccess.Read, FileShare.None) code? Any suggestions? thank you
If you want to keep the file locked for longer then you need to refactor your code so that the Stream object is kept around for longer - I would change the Read method to accept a FileStream, a little bit like this
using (FileStream fs = File.Open(myfile, FileMode.Open, FileAccess., FileShare.None))
{
List<string> = Read(fs);
if (something)
{
File.Move(/* somefile */)
}
}
The problem you are going to have is that File.Move method is going to fail as this file is already locked (by you, but File.Move doesn't know that).
Depending on what exactly it is you want to do it might be possible to work out a way of keeping the file locked while also "moving" the file, (for example if you know something in advance you could open the file specifying FileOptions.DeleteOnClose and write a new file with the same contents in the desired destination), however this isn't really the same as moving the file and so it all depends on what exactly it is you are trying to do.
In general such things are almost always going to be more trouble than they are worth - you are better off just unlocking the file just before you move it and catching/ handling any exception that is thrown as a result of the move.
The only way you could keep it locked is to keep it exclusively open, like you have done in your code.
Maybe you need to //do stuff within your using statement, and then straight after call Move
No amount of locking will prevent this. A lock only protects the data in the file. The user (or any other program) can still move or rename the file. The file's attributes, including name, time stamps and file attributes are stored separately and can be changed at will.
This is just something you'll have to deal with in any Windows program. It is rare enough that simply catching the exception is good enough to let you know that something happened to the file. The user will rarely be surprised. If you really need to know up front then you can use FileSystemWatcher to get a notification when it happens.
You are locking the file only when Read method is called.
If you want to keep it locked and release it only when you decide, make your methods OpenFile(string filename) and CloseFile(string filename). Then remove the using statement from Read method.
Open it when you start working (lock). Read it when you need it. When you have to move it, simply create a new file with the same name and copy the content. Close the original file (unlock) and delete it.
This question already has answers here:
File being used by another process after using File.Create()
(11 answers)
Closed 8 years ago.
I check to see if a file exists with
if(!File.Exists(myPath))
{
File.Create(myPath);
}
However, when I go to create a StreamReader with this newly created file, I get an error saying that
The process cannot access the file '[my file path here]' because it is being used by another process.
There isn't a File.Close(myPath) that I can call so that it is closed after being created, so how do I free this resource so that I can open it later in my program?
File.Create(string) returns an instance of the FileStream class. You can call the Stream.Close() method on this object in order to close it and release resources that it's using:
var myFile = File.Create(myPath);
myFile.Close();
However, since FileStream implements IDisposable, you can take advantage of the using statement (generally the preferred way of handling a situation like this). This will ensure that the stream is closed and disposed of properly when you're done with it:
using (var myFile = File.Create(myPath))
{
// interact with myFile here, it will be disposed automatically
}
The function returns a FileStream object. So you could use it's return value to open your StreamWriter or close it using the proper method of the object:
File.Create(myPath).Close();
File.Create returns a FileStream object that you can call Close() on.
The reason is because a FileStream is returned from your method to create a file. You should return the FileStream into a variable or call the close method directly from it after the File.Create.
It is a best practice to let the using block help you implement the IDispose pattern for a task like this. Perhaps what might work better would be:
if(!File.Exists(myPath)){
using(FileStream fs = File.Create(myPath))
using(StreamWriter writer = new StreamWriter(fs)){
// do your work here
}
}
File.WriteAllText(file,content)
create
write
close
File.WriteAllBytes-- type binary
:)