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

Posted

技术标签:

【中文标题】我应该在调用 File.Delete 之前调用 File.Exists 吗?【英文标题】:Should I call File.Exists before calling File.Delete? 【发布时间】:2013-01-02 19:41:33 【问题描述】:

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

finally

    //remove the temporary file
    if(File.Exists(transformedFile))
        File.Delete(transformedFile);

根据C# documentation,对不存在的文件调用 File.Delete 不会引发任何异常。

是否可以删除 File.Exists 包装,或者这会使我面临可能的其他异常?

【问题讨论】:

我之前问过的类似问题:***.com/questions/8823395/… @m-y 相似,但不重复 【参考方案1】:

如果你需要它,它是不够的,因为文件可以在你确认它存在之后被删除。在这种情况下,最佳做法是简单地尝试删除文件。如果它因“找不到文件”类型的错误而失败,那么您将知道该文件不存在。这消除了额外的操作并避免了任何类型的竞争窗口。

【讨论】:

关于比赛条件的要点。这不应该在我的代码中发生,但我们都知道“不应该发生”的事情会发生什么。 对。竞争条件是不这样做的一般原因。它也只是不需要。 当然,在您调用 delete 后,该文件仍可能由其他人重新创建,因此您的其他代码可能仍存在竞争条件...【参考方案2】:

在一种情况下,在Delete 之前检查Exists 可以防止异常。如果文件名的路径无效,Exists 方法将返回 false

那么这取决于你想要什么行为。在某些情况下,无效路径应该导致异常。

此外,仅仅因为文件存在并不意味着总是可以删除它(当时)。对于不可预见的问题,您仍然需要异常处理。

【讨论】:

我不太担心文件会留在那里,异常应该会冒泡到我们的日志记录层(另外,我真的不想在 finally 中尝试/捕获)。谢谢!【参考方案3】:

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

【讨论】:

【参考方案4】:

让我们从逻辑和批判的角度来看待这个问题。假设 MSDN doco 不是 100% 准确(它确实包含偶尔的错误)并且 FileNotFoundException 可能 被抛出,它可能由以下任一原因引起:

    文件从一开始就不存在(您在创建文件之前退出了try并输入了finally

    您遇到了程序错误(您错误地组装了文件路径或名称)

人们会假设选项 #2 不应该发生,因为您对此进行了测试,如果它仍然可以发生,那么您的代码很臭。这使得选项 #1 作为唯一可行的选项,在这种情况下,您不关心异常,因此您只需抓住它并继续前进。这意味着即使可以抛出 FileNotFoundException,您的具体问题也基本上是多余的。

但是... 我仍然会用 try/catch 包装 File.Delete,因为 IMVHO 仍然存在两个可能的异常,您需要注意:IOException 和 UnauthorizedAccessException。如果发生其中任何一种情况,您应该考虑某种缓解措施(可能设置文件以在下次重新启动时删除和/或以某种方式通知用户)。

【讨论】:

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

您仍然可以获得其他类型的异常。例如,如果文件正在使用,则出现 IOException。

因此,如果您坚持删除 finally 块中的文件并希望确保不会出现异常,只需在 File.delete 周围放置另一个 try-catch。

finally

   try 
   
     //remove the temporary file
     File.Delete(transformedFile);
   
   catch
   
   

但如果您的目标是在任何情况下删除文件,我认为如果您以独占方式打开文件会是个好主意,在这种情况下您应该先关闭文件然后删除 它。

【讨论】:

【参考方案6】:

我之前问过a similar question这个问题,我得出了这样的结论:

视情况而定。是的,我知道...这不是一个直接的答案,但这里有一些注意事项可以确定您的情况是否需要文件存在检查和/或 File.Delete(...) 方法周围的 try ... catch ... 块。

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

【讨论】:

是的,我可能希望其他异常只是冒泡,我不想抓住它们。

以上是关于我应该在调用 File.Delete 之前调用 File.Exists 吗?的主要内容,如果未能解决你的问题,请参考以下文章

NSFetchedResultsController:在调用 -performFetch 之前,我是不是应该始终检查 fetchedObjects==nil?

根据行业惯例,我应该在进行 API 调用之前还是在 Alamofire 中进行 API 调用期间检查互联网可访问性

我应该在我自己的代码之后还是之前调用 [super superMethod]?

在调用 InternetGetProxyInfo() 之前应该进行哪些初始化?

我应该在重新分配之前调用分配给保留属性的自动释放对象的释放吗?

在 applicationDidFinishLaunching 之前调用 viewDidLoad