在调用 File.Delete 前,我应该先调用 File.Exists 吗?

12

我的finally子句中有一个File.Delete,如下所示:

finally
{
    //remove the temporary file
    if(File.Exists(transformedFile))
        File.Delete(transformedFile);
}
根据C#文档,调用File.Delete删除不存在的文件不会引发任何异常。
删除File.Exists包装是否安全,是否可能导致额外的异常?

之前我问过类似的问题:https://dev59.com/2V_Va4cB1Zd3GeqPQytb - myermian
6个回答

14
如果您需要确认某个文件是否存在,仅仅检查它是不够的,因为在您确认其存在后,该文件可能会被删除。在这种情况下,最好的做法是尝试删除文件。如果删除失败并返回“找不到文件”类型的错误,则说明该文件不存在。这样可以避免额外的操作并防止竞争窗口。

竞争条件方面的观点很好。这在我的代码中不应该发生,但我们都知道“不应该发生”的事情会发生。 - Codeman
1
没错。竞态条件是不这样做的一般原因。而且这也没有必要。 - David Schwartz
当然,在您调用删除之后,该文件仍可能被其他人重新创建,因此您的其他代码仍可能存在竞争条件... - AyCe

10

有一种情况,在执行Delete方法之前检查Exists可以避免异常。如果您的文件名包含无效路径,则Exists方法返回false

这取决于您希望出现什么行为。在某些情况下,无效路径应该引发异常。

此外,仅因为文件存在并不意味着始终可以删除它(在那个时间)。您仍需要针对未预见问题进行异常处理。


我不太关心文件是否留在那里,异常应该冒泡到我们的日志记录层(而且我真的不想在我的finally中使用try/catch)。谢谢! - Codeman

5

File.Delete并不会抛出FileNotFoundException异常,它并不关心这个文件是否存在。 只有当路径无效时,例如具有不存在的目录时,它才会引发异常,此时将引发DirectoryNotFoundException异常。

这段代码不会引发任何异常。

var file = new FileInfo(@"C:\doesnotexist.file11111");
file.Delete();

这将抛出DirectoryNotFoundException

var file = new FileInfo(@"C:\bad.dir\doesnotexist.file11111");
file.Delete();

MSDN File.Delete


1
你仍然可能会遇到其他类型的异常。例如,如果文件正在使用中,则可能会出现IOException异常。
因此,如果你坚持要在finally块中删除文件,并且想确保不会出现异常,请在File.delete周围再加一个try-catch。
finally
{
   try 
   {
     //remove the temporary file
     File.Delete(transformedFile);
   }
   catch
   {
   }
}

但是如果您的目标是无论如何都要删除文件,我认为最好的方法是独占式地打开文件,在这种情况下,您应该先关闭文件,然后再删除它。


1

让我们逻辑和批判性地看待这个问题。假设 MSDN 文档不是 100% 准确的(它确实包含偶尔出现的错误),并且可能会抛出 FileNotFoundException 异常,那么它可能是由以下原因之一导致的:

  1. 文件根本不存在(您在创建文件之前退出了 try 并进入了 finally

  2. 您存在编程错误(您已经错误地组装了文件路径或名称)

人们会认为选项 #2 不应该发生,因为您已经进行了测试,如果它仍然可以发生,则说明您的代码有问题。这意味着选项 #1 是唯一可行的选择,如果是这种情况,您不需要关心异常,因此只需捕获它并继续执行即可。即使可能会抛出 FileNotFoundException 异常,这意味着您的具体问题在很大程度上是多余的。

然而...
我仍然会在File.Delete周围加上try/catch,因为在我看来仍然有两种可能的异常需要注意:IOExceptionUnauthorizedAccessException。如果其中任何一种发生,您应该考虑采取某种缓解措施(也许是设置文件在下次重启时删除和/或以某种方式通知用户)。


1
虽然我不否认MSDN文档并非100%准确,但在这种情况下它是正确的。如果文件不存在,File.Delete()不会抛出任何异常。 - myermian
1
@m-y 是的,这是一个假设情况,但我正在尝试帮助OP自己分析这样的情况,分析思维是编程的关键部分。无论如何,到目前为止,所有其他答案都集中在FileNotFound问题上,忘记了问题的第二部分... - slugster

0

我之前曾经问过一个类似的问题,并得出了以下结论:

这取决于具体情况。是的,我知道...这不是一个直截了当的答案,但以下是一些需要注意的事项,以确定您的情况是否需要进行文件存在检查和/或在File.Delete(...)方法周围使用try { ... } catch { ... }块。

  • 您的代码是否生成了该文件?如果是,则实际上不需要检查文件是否存在。
  • 您是否关心处理其他问题?请记住,您正在使用文件系统,MSDN文档清楚地显示该方法可能由于其他情况而生成异常。

是的,我可能希望其他异常只是冒泡而不想捕获它们。 - Codeman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接