刚删除后为什么我不能创建一个txt文件?

时间:2011-12-29 16:18:52

标签: c# logging io delete-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());
                }
            }
        }

因为我已经完全删除了日志文件,所以我需要重新创建它。所以我称之为一个方法:

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

但是当它尝试重新创建日志文件时,会抛出一个错误:

  

“System.IO.IOException:进程无法访问文件'~~',因为它正由另一个进程使用。”

所以看来我在删除文件的过程中一直在访问它?当我致电file.delete时,我是否需要处理某些事情?

4 个答案:

答案 0 :(得分:6)

我不知道详细信息,但是有很多原因可以解释为什么在删除现有文件后文件名无法立即用于重新创建:

  • 操作系统仍在等待删除操作
  • 防病毒程序或类似安全功能打开文件以响应其被删除,以进行删除前分析
  • 防病毒程序或类似的安全功能在您使用该文件时已打开该文件,并且仍在响应您的删除请求

Mercurial也在Windows上遇到此问题。如果您执行了一个锁定存储库的命令(使用临时文件完成),然后立即执行另一个需要锁定的命令,或者至少确保没有锁定,那么它可能会因同一类型的错误而失败,文件正在使用中,即使这是两个不同的进程,第一个已经退出。

换句话说,时间表如下:

  • hg.exe实例#1启动,通过创建临时文件锁定存储库
  • hg.exe执行它需要做的事情
  • hg.exe删除该文件,然后退出
  • hg.exe实例#2启动,尝试锁定存储库,因文件正在使用而失败

他们“修复”这个问题的方法是简单地选择一个未在目录中使用的随机文件名,将文件重命名为该名称,然后将其删除。这并没有解决文件遗留一段时间的问题,但它确实释放了文件名并立即将其用于新文件。

答案 1 :(得分:4)

已经有一个公认的答案,但也许有人觉得这很有用(或者如果我再次错过了一些明显的东西并且完全浪费了我的时间,那就嘲笑它)

我的印象是File.Delete要么删除文件然后返回,要么抛出异常 - 直到我读到这个帖子。

Windows API提到,通过调用DeleteFile文件被“标记为关闭时删除”,因为它允许在打开的文件上调用delete。将文件标记为删除后,尝试打开该文件将失败,因为“拒绝访问”。当关闭此文件的最后一个句柄时,实际上会删除该文件。

如果windows在从文件的最后一次CloseHandle调用返回之前实际删除了文件,理论上这段代码可以保证文件在using块下面被删除:

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

如果另一个进程当前打开了文件,File.Open将失败。

请注意,如果文件不存在,File.Delete甚至会成功(除非该目录不存在)。

答案 2 :(得分:3)

您可以清除它,而不是删除并重新创建相同的文件吗?

这样的事情对你有用:

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

答案 3 :(得分:0)

您可以使用System.IO.FileInfo.Delete删除文件,然后再使用System.IO.FileInfo.Refresh()再次创建文件。刷新应该在重新创建文件时停止发生异常。或者如nycdan所说,使用FileMode.Create枚举。