在异常处理方面,删除文件的最有效方法是什么?

本文关键字:有效 方法 是什么 文件 异常处理 方面 删除 | 更新日期: 2023-09-27 18:05:14

MSDN告诉我们,当你调用"File。Delete(path);"如果文件不存在,则生成异常。

调用delete方法并使用try/catch块来避免错误或在执行删除操作之前验证文件的存在性是否更有效?

我倾向于认为最好避免try/catch块。当你知道如何检查错误时,为什么要让错误发生呢?

无论如何,这里是一些示例代码:

// Option 1: Just delete the file and ignore any exceptions
/// <summary>
/// Remove the files from the local server if the DeleteAfterTransfer flag has been set
/// </summary>
/// <param name="FilesToSend">a list of full file paths to be removed from the local server</param>
private void RemoveLocalFiles(List<string> LocalFiles)
{
    // Ensure there is something to process
    if (LocalFiles != null && LocalFiles.Count > 0 && m_DeleteAfterTransfer == true)
    {
        foreach (string file in LocalFiles)
        {
            try { File.Delete(file); }
            catch { }
        }
    }
}
// Option 2: Check for the existence of the file before delting
private void RemoveLocalFiles(List<string> LocalFiles )
{
    // Ensure there is something to process
    if (LocalFiles != null && LocalFiles.Count > 0 && m_DeleteAfterTransfer == true)
    {
        foreach (string file in LocalFiles)
        {
            if( File.Exists( file ) == true)
                File.Delete(file);
        }
    }
}

我想要实现的一些背景:该代码是FTP包装器类的一部分,该包装器类将简化FTP功能的特性,只保留需要的并且可以通过单个方法调用来调用的特性。在本例中,我们有一个名为"DeleteAfterTransfer"的标志,如果设置为true将完成这项工作。如果文件一开始就不存在,那么我希望在到达这一点之前发生异常。我想我在这里回答了我自己的问题,但是检查文件的存在性不如验证我是否有执行任务的权限或任何其他潜在错误重要。

在异常处理方面,删除文件的最有效方法是什么?

考虑到当文件不在那里时 File.Delete不会抛出异常,您基本上有三个选择:

  • 使用文件。存在,这需要每次额外往返磁盘(归功于Alexandre C),加上往返到磁盘的File.Delete。这是缓慢的。但是如果你想在文件不存在的情况下做一些特别的事情,这是唯一的方法。

  • 使用异常处理。考虑到进入try/catch块相对较快(我相信大约4-6 m-ops),开销可以忽略不计,并且您可以选择捕获特定的异常,例如文件正在使用时的IOException。这是非常有益的,但是当文件不存在时,您将无法执行操作,因为这不会抛出。

  • 注意:这是避免竞态条件最简单的方法,Alexandre C会在下面做更详细的解释。
  • 同时使用异常处理 File.Exists。这可能是最慢的,但只是稍微慢一点,并且当文件不存在时,捕获异常执行特定操作(发出警告?)的唯一方法。


对我最初的回答的总结,给出一些关于使用和处理异常的更一般的建议:

  • 当控制流足够时,不要使用异常处理,这样更有效,更可读。
  • 仅在异常情况下使用异常和异常处理。
  • 异常处理进入try/catch是非常有效的,但是当一个异常被抛出时,这花费相对较多。
  • 上述的一个例外是:无论何时处理文件函数,使用异常处理。原因是可能会发生竞态条件,并且您永远不知道if语句和file-delete语句之间发生了什么。
  • 永远不要,我的意思是:永远不要对所有异常使用try/catch(空catch块),这几乎总是应用程序中的一个弱点,需要改进。只捕获特定的异常。(例外:当处理COM异常不继承Exception时)。

另一个选项:使用Windows API DeleteFile…

[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool DeleteFile(string path);

如果完成则返回true,否则返回false。如果为false,则没有异常的大开销。

MSDN表示未生成异常。实际上,这样做更好,因为你有一个竞争条件:在调用File.ExistsFile.Delete之间,文件可能已经被另一个进程删除或创建。

如果

要抛出,最好是捕获可能抛出的特定的异常(FileNotFoundException或类似)。注意,由于存在竞争条件,异常是唯一的方法。

如果您的问题是包含文件的目录不存在,那么您可以执行:

if (LocalFiles != null && m_DeleteAfterTransfer == true)
{
    foreach (string file in LocalFiles)
    {
        try { File.Delete(file); }
        catch (DirectoryNotFoundException e) {}
    }
}
同样,在此之前不要检查目录是否存在,因为1)它很麻烦2)它有相同的竞争条件问题。只有File.Delete保证自动执行检查和删除

无论如何,您永远不会想要捕获这里的每个异常,因为文件IO方法可能由于许多原因而失败(并且您肯定不想沉默磁盘故障!)

在尝试删除文件时可能发生许多异常。在这里看看所有的。所以最好在你认为合适的时候抓住并处理它们。

您应该使用File.Exists,但无论如何都要处理异常。一般来说,在两个调用之间删除文件是可能的。处理异常仍然有一些开销,但是首先检查文件是否存在可以将抛出频率降低到几乎不发生。对于上述场景发生的百万分之一的可能性,您仍然可以使用未处理的异常破坏某人的工作。

在一般情况下,在调用方法之前测试异常情况确实更好,因为异常不应该用于控制流。

然而,我们在这里处理的是文件系统,即使您在删除它之前检查该文件是否存在,也可能会在两次调用之间删除它。在这种情况下,Delete()仍然会抛出一个异常,即使你显式地确保它不会。

所以,在这种特殊情况下,我无论如何都要准备好处理异常。

我认为你不仅要考虑效率,还要考虑意图。问自己这样的问题:

  • 文件列表包含不存在的文件是错误的情况吗?
  • 您是否为其他可能导致删除文件失败的错误而烦恼?
  • 如果发生除"文件未找到"以外的错误,该过程是否继续?

显然,即使文件存在,Delete调用也可能失败,所以只添加检查并不能保护你的代码免于失败;您仍然需要捕获异常。问题更多的是关于捕获和处理哪些异常,以及哪些异常应该向上传递给调用者。

最好先做File.Exists。异常的开销很大。在效率方面,你的定义不是很清楚,但性能和内存方面,选择File.Exists

请参阅我之前关于使用异常来控制程序流程的问题的回答:

使用异常控制流程的示例

如下所示,我欢迎任何人自己尝试。人们谈论的主轴速度和访问时间的硬盘驱动器-这是非常不相干的,因为我们没有计时。OP问他完成任务最有效的方法是什么。正如你在这里可以清楚地看到,它是使用File.Exists。:

实际记录的性能结果:try/catch vs File。存在于不存在的文件

文件数(不存在): 10,000

:http://pastebin.com/6KME40md

结果:

RemoveLocalFiles1 (try/catch): 119ms

RemoveLocalFiles2 (File.Exists): 106ms