简体   繁体   中英

Why can't I create a txt file after having just deleted it?

My program creates a log file when it starts. The user has the option through settings to "clear the log" which calls a method to delete the log file.

        //calls for a YesNo prompt to delete log or not
        result = objectMessageBox.ReturnDeleteLogPrompt();

        if (result == DialogResult.Yes)
        {
            //throw prompt
            if (File.Exists(objectLog.GetLogLocation()) == true)
            {
                try
                {                        
                    //delete the log file
                    File.Delete(objectLog.GetLogLocation());                        

                    //throw balloon tip saying log was cleared
                    ShowBalloonTip("LogCleared");
                }
                catch (Exception ee)
                {
                    MessageBox.Show("Error thrown deleting log: " + ee);
                    System.Windows.Forms.Clipboard.SetText(ee.ToString());
                }
            }
        }

Because I have deleted the log file entirely I need to then recreate it. So I call a method that has this:

try
        {
            //we create a new log file so it seems that the log has just been cleared
            objectLog.CreateLog();
        }
        catch (Exception ee)
        {
            MessageBox.Show("Error occured while clearing log:\n" + ee);
        }

But when it attempts to recreate the log file it throws an error that says:

"System.IO.IOException: The process cannot access the file '~~' because it is being used by another process."

So it seems that during my call to delete the file it keeps accessing it? Do I need to dispose of something when I call the file.delete ?

I don't know the details, but there are numerous reasons for why a filename isn't immediately available for recreation after deleting an existing file:

  • The delete operation is still pending by the operating system
  • An antivirus program or similar security feature opened up the file in response to it being deleted, for pre-deletion analysis
  • An antivirus program or similar security feature already had the file open while you were using it, and is still in the progress of responding to your deletion request

Mercurial had this problem on Windows as well. If you executed one command that locked the repository (which was done using temporary files), and then immediately executed another command that either needed to lock, or at least ensure no lock was present, it could fail with the same type of error, the file was in use, even though this was two distinct processes and the first had already exited.

In other words, the timeline was as follows:

  • hg.exe instance #1 starts up, locks the repository by creating the temp file
  • hg.exe does what it needs to do
  • hg.exe deletes the file, then exits
  • hg.exe instance #2 starts up, attempts to lock the repository, fails because file is in use

Their hack to "fix" this was to simply pick a random filename that wasn't used in the directory, rename the file to that name, and then delete it. This did not solve the problem of the file lingering for a short while, but it did free up the filename and make it available for new files right away.

There already is an accepted answer, but perhaps someone finds this useful (or laugh at it if I missed something obvious again and wasted my time completely)

I had the impression that File.Delete would either delete the file and then return, or otherwise throw an exception - until I read this thread.

The windows API mentions that by calling DeleteFile the file is "marked for deletion on close" since it allows calling delete on an open file. After a file is marked for deletion, an attempt to open it will fail as "Access denied". When the last handle for this file is closed, the file is actually deleted.

If windows actually deletes the file before returning from the last CloseHandle call on the file, in theory this code would guarantee that the file is deleted below the using block:

using (File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Delete))
{
    File.Delete(path);
}

The File.Open would fail if another process currently has the file open.

Note the difference here that File.Delete even succeeds if a file does not exist (unless the directory does not exist).

Instead of deleting and recreating the same file, can you just clear it out?

Something like this should work for you:

FileStream f = File.Open(@[filename], FileMode.Create);
f.Close();

You could use System.IO.FileInfo.Delete to delete the file, and then System.IO.FileInfo.Refresh() before creating the file again. The Refresh should stop the exception from happening on re-creating the file. Or as nycdan says, use the FileMode.Create enum.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM