【问题标题】:How to check if System.IO.File.Delete deleted a file successfully如何检查 System.IO.File.Delete 是否成功删除文件
【发布时间】:2013-01-04 16:10:38
【问题描述】:

使用 system.io.file 类删除文件后:

System.IO.File.Delete(openedPdfs.path);

如果文件被成功删除,我需要运行一些代码。 只要该方法不返回任何值,我就会在删除方法之后检查文件是否存在。如果它仍然存在,我认为操作失败了。

问题是,删除方法工作正常,但要删除的文件有几秒钟的时间。 Exist 函数返回 true 是因为它正在检查文件是否存在。

如何确定System.IO.File.Delete(openedPdfs.path); 是否成功完成?

代码:

FileInfo file = new FileInfo(openedPdfs.path);    
System.IO.File.Delete(openedPdfs.path);
if (file.Exists == false)
{ ... }
else 
{ ... }

【问题讨论】:

  • “我能想到的最优雅的方式是使用FileSystemWatcher 并订阅它的Deleted 事件。” stackoverflow.com/questions/9370012/…
  • 您是否担心删除成功,但在检查是否存在之前创建了一个同名的新文件?
  • @TimSchmelter FileSystemWatcher 已报告在负载下丢弃事件。有些人建议它可以用来提高响应能力,但他们仍然会以缩短的间隔进行轮询,以确保不会错过事件。 FSW 也可能会降低性能,尤其是在过滤器过于粗糙的情况下。

标签: c# asp.net .net asp.net-mvc asp.net-mvc-4


【解决方案1】:

正如其他人指出的那样,File.Delete 方法会在失败的情况下抛出异常。

他们没有指出的是,几乎所有情况都会抛出异常,但并非所有情况。具体来说,如果要删除的文件碰巧不存在,File.Delete 方法将不会抛出异常。 (呃?他们在想什么?)

因此,您应该检查文件是否存在之前删除它;如果它不存在,你不应该做任何事情。如果它存在,你应该调用File.Delete,如果它抛出一个异常,那么你不应该做任何事情,因为文件没有被删除。否则,您应该执行成功后删除现有文件的操作。

【讨论】:

  • 虽然不是 MS 辩护者,但我认为 .NET 设计避免在大多数情况下调用者不关心文件被删除的方式或时间时引发异常。异常不是报告不太有趣的结果的一种非常高效的方式。 Directory.Create 遵循相同的模式。它再次通过不报告目录的先前存在来解决竞争条件。在大多数用例中,这无关紧要。 WinAPI 通过在整数返回值中明确报告发生或未发生的事情来处理此问题,而不会引发代价高昂的异常。
  • @AndrewDennison 和我并不是要在每一个机会中贬低微软,但 .Net 中的例外是如此可怕且不必要地昂贵,以至于它们促使开发人员做出蹩脚的设计决策以避免这种成本.我怎么知道它们的成本是不必要的?好吧,我没有证据证明这一点,但我在每种语言多年编程后的印象是,java 中的异常虽然代价高昂,但并不像 dotNet 中那样昂贵。
【解决方案2】:

Delete 如果文件没有被删除,应该抛出异常。因此,您对Exists 的调用是多余的。

看看documentation for Delete

【讨论】:

  • 从 File.Delete 完成到文件实际被删除有一点延迟。
  • -1:你的第一句话是错误的。当文件之前不存在(因此不会被删除)时,删除不会抛出。仔细查看Delete的文档:“如果要删除的文件不存在,则不抛出异常。”
【解决方案3】:

这是 Daniel A. White 的辅助答案:我们可以看到 the signature for the methodpublic static void Delete(string path)。很明显,除非例外,否则您不会从 Delete 调用中获得反馈。但是让我们假设您有一个文件被另一个进程定期写入或更新:

  1. 您的程序已成功删除该文件。
  2. 另一个进程在删除后立即重新创建它。
  3. 您的程序使用file.Exists 测试是否存在。有一个同名的新文件,因此返回 true。从技术上讲,您走错了路。

对于您当前尝试解决的问题,这种确切的情况可能不正确,但检查 Delete 调用是否引发异常比依赖当前实现更可靠。

【讨论】:

    【解决方案4】:

    你可以随时使用

     System.IO.File.Exists(path)
    

    虽然我同意丹尼尔的观点,但如果 Delete 没有抛出异常,你应该是好的。

    【讨论】:

      【解决方案5】:

      从 cmets 和建议中,您应该能够使用以下内容来实现您想要的结果

      try {
        FileInfo file = new FileInfo(openedPdfs.path);    
        System.IO.File.Delete(openedPdfs.path);
        // if no exception is thrown then you should assume all has gone well and put  
        // your file successfully deleted code here.
      } catch /*(Specfic exceptions can be referenced here in separate catch blocks see Daniel A. White answer)*/ {
        // If something bad happened and the file was not deleted put handling code here
      } finally {
        // if some action needs to be taken regardless of whether the file was successfully deleted or not put 
        // that code here
      }
      

      【讨论】:

        【解决方案6】:

        如果文件不存在,它不会抛出异常。如果出现错误,如果无法删除会抛出异常,请检查File.Delete

        【讨论】:

        • 文档说“如果要删除的文件不存在,则不抛出异常。”
        • @MobyDisk 是的,但我的意思是它会在出错的情况下抛出异常。从技术上讲,删除不存在的文件并没有错误。
        【解决方案7】:

        我发现如果使用 FileInfo Delete() 实例方法,FileInfo 实例属性 Exists 不会更新。
        例如,以下代码将抛出一个找不到文件的异常,因为该文件已被删除,但第二个 if (output_file.Exists) 仍然评估为真。

        FileInfo output_file;
        if (output_file.Exists) output_file.Delete();   
        
        FileStream fs;
        if (output_file.Exists)
        {
             fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.ReadWrite);
        }
        else
        {
             fs = new FileStream(fi.FullName, FileMode.CreateNew, FileAccess.ReadWrite);
        }
        

        我发现从旧文件创建一个新的 FileInfo 解决了这个问题:

        FileInfo output_file;
        if (output_file.Exists)
        {
            output_file.Delete();
            output_file = new FileInfo(output_file.FullName);      
        }
        
        FileStream fs;
        if (output_file.Exists)
        {
             fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.ReadWrite);
        }
        else
        {
             fs = new FileStream(fi.FullName, FileMode.CreateNew, FileAccess.ReadWrite);
        }
        

        【讨论】:

        • 您可以使用output_file.Refresh() 来刷新FileInfo 的状态。另外,这如何回答这个问题?
        【解决方案8】:
        private String del(String fileLocation) {
        
         if (File.Exists(@fileLocation)) {
          try {
           File.Delete(@fileLocation);
          } catch (Exception e) {
           return "File couldn't be deleted because: " + e.GetType().Name;
          }
         } else {
          return "File doesn't exist";
         }
        
         return "File successfully deleted";
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-11-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-07
          • 2011-09-17
          • 1970-01-01
          相关资源
          最近更新 更多