IO Exception - a file in use by another process (cannot open file after directory creation)
I have an on-the-go project that monitors vet patients while they are working and writes the result to a text file. While I was experimenting with the pins, I just left the files in the Debug folder that worked fine. However, I have now created a full directory that creates or opens the main folder and then a sub folder (based on text input from the program) to save the text file.
private void createDirectory()
{ //create output file in this folder using owner name and current date
//main folder path (contains all files output from system)
string rootDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Horse Monitoring Records";
//sub folder path (each patient has individual subfolder)
string subDirectory = rootDirectory + "\\" + txtPatName.Text + "-" + txtOwnerName.Text;
//file name (patient has file created for each operation)
fileName = subDirectory + "\\" + txtOwnerName.Text + "-" + DateTime.Now.Date.ToString("ddMMyyyy") + ".txt";
if (!Directory.Exists(rootDirectory)) //if main folder does not exist...
{
Directory.CreateDirectory(rootDirectory); //create it in My Documents
}
if (!Directory.Exists(subDirectory)) //if patient sub folder does not exist...
{
Directory.CreateDirectory(subDirectory); //create it in Patient-Owner format
}
if (!File.Exists(fileName)) //if monitoring file does not exist...
{
File.Create(fileName); //create it in Owner-Date format
}
}
This step works fine, but as soon as you try to store some data in a text file, it throws a runtime error stating that
The file cannot be accessed because it is being used by another process.
Here's the exception:
private void saveFileDetails()
{
//Once case details have been entered, create new file using these details and add data input structure
StreamWriter consoleFile = new StreamWriter(fileName);
...
}
When I went and checked the folder, the corresponding subfolder and file was created, but the text file was empty. I am guessing it has to do with closing the text file after the directory has been created, which means it is already open when the system tries to open it. I can't figure out how to sort this issue though!
The above two functions are named like this:
private void btnStart_Click(object sender, EventArgs e)
{
...
//file details entered upon load written to new file - according to PatID
createDirectory();
saveFileDetails();
}
Any suggestions on where to go from here would be greatly appreciated!
Thanks Mark
source to share
The problem is what you do
if (!File.Exists(fileName)) //if monitoring file does not exist...
{
File.Create(fileName); //create it in Owner-Date format
}
Before trying to write to a file. Since you just created it (if it didn't exist), chances are the operating system hasn't released the file yet.
Similar to @Jauch mentioned in the comments, you can skip this check entirely and use an overload StreamWriter
that will create the file if it doesn't exist, or add to it if it does.
private void saveFileDetails()
{
//Once case details have been entered, create new file using these details and add data input structure
using (StreamWriter consoleFile = new StreamWriter(fileName, true))
{
// ...
}
}
Alternatively, you can use the following to write the entire text at once:
File.AppendAllText(textToWrite, fileName);
source to share
File.Create(fileName)
returns an open stream to a file that is never closed.
To create an empty file use File.WriteAllBytes(fileName, new byte[0]);
Otherwise 2 methods can be shortened
private void SaveFileDetails()
{
string subDirectory = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"Horse Monitoring Records");
// create the folder hierarchy if not exists. does nothing if already there
Directory.CreateDirectory(subDirectory);
// each patient has individual file
var filepath = Path.Combine(subDirectory,
txtPatName.Text + "-" + txtOwnerName.Text + "-" + DateTime.Now.Date.ToString("yyyyMMdd") + ".txt");
// creates the file if not exists
using (var writer = new StreamWriter(filepath, append: true, encoding: Encoding.UTF8))
{
// write details
}
}
Note:
- combined 2 methods
- .NET naming conventions used
- changed date format to sort better by name in explorer
source to share
StreamWriter
implements IDisposable
, so using it in a use block can manage the closing and deletion of a record and ensure that it is available the next time you want to touch that file. It can also control the creation of a text file if it doesn't exist, eliminating the need for an explicit call File.Create
.
StreamWriter consoleFile = new StreamWriter(fileName);
becomes
using (StreamWriter writer = File.AppendText("log.txt"))
{
// writing, etc.
}
or
using (StreamWriter writer = new StreamWriter(fileName, true))
{ // true says "append to file if it exists, create if it doesn't"
// writing, etc.
}
Anything that seems more readable to you works great.
source to share