3

I have the following code:

// get location where application data director is located
var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

// create dir if it doesnt exist
var folder = System.IO.Path.Combine(appData, "SomeDir");
if (System.IO.Directory.Exists(folder) == false)
    System.IO.Directory.CreateDirectory(folder);

// create file if it doesnt exist
var file = System.IO.Path.Combine(folder, "test.txt");
if(System.IO.File.Exists(file)== false)
     System.IO.File.Create(file);

// write something to the file
System.IO.File.AppendAllText(file,"Foo");

This code crashes on the last line (An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll). If I put a Thread.Sleep(400) after creating the file the code works great. What is the proper way of waiting until the file is created?

P.S. I am using .net framework 3.5

Even if I wait it crashes :/

enter image description here

Tono Nam
  • 34,064
  • 78
  • 298
  • 470
  • 1
    I think you don't need to create it as AppendAllText should create file if it doesn't exist. Also it is probably the reason of exception as file is opened when you try to append text. For other files you can also use "using" statement. – Immons Oct 03 '15 at 19:42
  • 1
    System.IO.File.AppendAllText creates a file if it doesn't exist already, so you wouldn't have to create it first. I can only assume that the call to File.Create creates a FileStream object that is cleaned up, but not fast enough to not block the file while your call to AppendAllText happens. – Dirk Trilsbeek Oct 03 '15 at 19:43
  • Sorry for the dumb question. I guess I am to tired lol – Tono Nam Oct 03 '15 at 19:47

2 Answers2

4

There is no need to create the file if you intend to use File.AppendAllText

About the root cause for the error, and a preferred way to write to files in general:

The file was created, and returned a stream that you didn't use/close. best method should be to use this stream to write to the file.

using (FileStream fs = File.Create(file))
{
     fs.Write("What ever you need to write..");
}
Yosi Dahari
  • 6,794
  • 5
  • 24
  • 44
4

The reason for that is because File.Create is declared as:

public static FileStream Create(
    string path
)

It returns a FileStream. The method is supposed to be used to create and open a file for writing. Since you never dispose of the returned FileStream object you're basically placing your bets on the garbage collector to collect that object before you need to rewrite the file.

So, to fix the problem with the naive solution you should dispose of that object:

System.IO.File.Create(file).Dispose();

Now, the gotcha here is that File.AppendAllText will in fact create the file if it does not exist so you don't even need that code, here is your full code with the unnecessary code removed:

// get location where application data director is located
var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

// create dir if it doesnt exist
var folder = System.IO.Path.Combine(appData, "SomeDir");
System.IO.Directory.CreateDirectory(folder);

// write something to the file
var file = System.IO.Path.Combine(folder, "test.txt");
System.IO.File.AppendAllText(file,"Foo");

Directory.CreateDirectory will likewise not crash if the folder already exists so you can safely just call it.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825