就异常处理而言,删除文件最有效的方法是什么?

发布于 2024-11-29 08:52:33 字数 1528 浏览 0 评论 0原文

MSDN 告诉我们,当您调用“File.Delete( path );”时对于不存在的文件,会生成异常。

在删除之前调用删除方法并使用 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 将完成这项工作。如果该文件一开始就不存在,我预计在到达这一点之前会出现异常。 我想我在这里回答了我自己的问题,但检查文件是否存在不如验证我是否有权执行该任务或任何其他潜在错误重要。

MSDN tells us that when you call "File.Delete( path );" on a file that doesn't exist an exception is generated.

Would it be more efficient to call the delete method and use a try/catch block to avoid the error or validate the existence of the file before doing the delete?

I'm inclined to think it's better to avoid the try/catch block. Why let an error occur when you know how to check for it.

Anyway, here is some sample code:

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

Some Background to what I'm trying to achieve:
The code is part of an FTP wrapper class which will simplify the features of FTP functionality to only what is required and can be called by a single method call.
In This case, we have a flag called "DeleteAfterTransfer" and if set to true will do the job. If the file didn't exists in the first place, I'd expect to have had an exception before getting to this point.
I think I'm answering my own question here but checking the existence of the file is less important than validating I have permissions to perform the task or any of the other potential errors.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

淡墨 2024-12-06 08:52:34

考虑到File.Delete 不会引发异常


我原来的答案的总结,给出了一些关于使用和处理异常的更一般的建议:

  • 当控制流足够时,不要使用异常处理,这只是更高效和更具可读性。
  • 仅对异常情况使用异常和异常处理。
  • 异常处理进入try/catch是非常高效的,但是当抛出异常时,这样的代价就比较大了。
  • 上述的一个例外是:每当处理文件函数时,请使用异常处理。原因是可能会发生竞争条件,并且您永远不知道 if 语句和文件删除语句之间会发生什么。
  • 从来没有,我的意思是:永远不要对所有异常使用try/catch(空catch块,这几乎总是应用程序中的一个弱点,需要改进。只捕获特定的异常。(异常:处理不继承自 Exception 的 COM 异常时)。

You have essentially three options, considering that File.Delete does not throw an exception when your file isn't there:

  • Use File.Exists, which requires an extra roundtrip to the disk each time (credits to Alexandre C), plus a roundtrip to the disk for File.Delete. This is slow. But if you want to do something specific when the file doesn't exist, this is the only way.

  • Use exception handling. Considering that entering a try/catch block is relatively fast (about 4-6 m-ops, I believe), the overhead is negligible and you have the option to catch the specific exceptions, like IOException when the file is in use. This can be very beneficial, but you will not be able to act when the file does not exist, because that doesn't throw. Note: this is the easiest way to avoid race conditions, as Alexandre C explains below in more detail.

  • Use both exception handling and File.Exists. This is potentially slowest, but only marginally so and the only way to both catch exceptions and do something specific (issue a warning?) when the file doesn't exist.


A summary of my original answer, giving some more general advice on using and handling exceptions:

  • Do not use exception handling when control flow suffices, that's simply more efficient and more readable.
  • Use exceptions and exception-handling for exceptional cases only.
  • Exception handling entering try/catch is very efficient, but when an exception is thrown, this costs relatively much.
  • An exception to the above is: whenever dealing with file functions, use exception handling. The reason is that race conditions may happen and that you never know what occurs between your if-statement and your file-delete statement.
  • Never ever, and I mean: never ever use a try/catch for all exceptions (empty catch block, this is almost always a weak point in your application and needs improvement. Only catch specific exceptions. (exception: when dealing with COM exceptions not inheriting from Exception).
叹梦 2024-12-06 08:52:34

另一种选择:使用 Windows API DeleteFile...

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

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

Another option: use Windows API DeleteFile...

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

This returns true if done, otherwise false. If false, you don't have the large overhead of Exceptions.

吃兔兔 2024-12-06 08:52:34

MSDN< /a> 表示不会生成异常。 实际上,这种方式更好,因为存在竞争条件:在对 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方法可能会因多种原因而失败(并且您当然不想消除磁盘故障!)

MSDN says that no exception is generated. Actually, it is better this way since you have a race condition: between calls to File.Exists and File.Delete the file could have been deleted or created by another process.

If it were to throw, you are better catching the specific exception that could have been thrown (FileNotFoundException or similar). Note that because of the race condition, exceptions are the only way to go here.

If your problem is that the directory containing the file doesn't exist, then you can do:

if (LocalFiles != null && m_DeleteAfterTransfer == true)
{
    foreach (string file in LocalFiles)
    {
        try { File.Delete(file); }
        catch (DirectoryNotFoundException e) {}
    }
}

Again, don't check for the directory existence before, because 1) it is cumbersome 2) it has the same race condition problem. Only File.Delete guarantees that the check and the delete are atomically executed.

Anyways you never want to catch every exception here since file IO methods can fail for a lot of reasons (and you surely don't want to silent a disk failure !)

往日情怀 2024-12-06 08:52:34

尝试删除文件时可能会发生许多异常。请在此处查看所有这些内容。因此,最好按照您认为合适的方式抓住并处理它们。

There are many exceptions that can occur when trying to delete a file. Take a look here for all of them. So it's probably best to catch and deal with each of them as you see fit.

过去的过去 2024-12-06 08:52:34

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

You should use File.Exists, but handle the exception anyway. In general it may be possible for the file to be deleted in between the two calls. Handling the exception still has some overhead, but checking the file for existence first reduces the throw frequency to almost-never. For the one in a million chance that the above scenario occurs, you could still ruin someone's work with an unhandled exception.

煮茶煮酒煮时光 2024-12-06 08:52:34

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

但是,我们在这里处理文件系统,即使您在删除文件之前检查文件是否存在,其他东西也可能会在两次调用之间删除它。在这种情况下,Delete() 仍然会抛出异常,即使您明确确保它不会抛出异常。

因此,在这种特殊情况下,我无论如何都会准备好处理异常。

In the general case, it's indeed better to test for the exceptional case before calling the method, as exceptions should not be used for control flow.

However, we're dealing with the filesystem here, and even if you check that the file exists before deleting it, something else might remove it between your two calls. In that case, Delete() would still throw an exception even if you explicitly made sure it wouldn't.

So, in that particular case, I would be prepared to handle the exception anyway.

树深时见影 2024-12-06 08:52:34

我认为你不仅应该担心效率,还应该担心意图。问自己这样的问题:

  • 文件列表中包含不存在的文件是否属于错误情况?
  • 您是否担心可能导致删除文件失败的任何其他错误?
  • 如果发生“找不到文件”以外的错误,该过程是否应该继续?

显然,即使文件存在,Delete 调用也可能会失败,因此仅添加该检查并不能保护您的代码免遭失败;你仍然需要捕获异常。问题更多的是要捕获和处理什么异常,以及哪些异常应该向上冒泡给调用者。

I think you should not only worry about efficiency, but also intention. Ask yourself questions like

  • Is it a faulty case that the list of files contains files that don't exist?
  • Do you bother about any of the other errors that can be the cause of failing to delete the file?
  • Should the process continue if errors other than "file not found" occurs?

Obviously, the Delete call can fail even if the file exists, so only adding that check will not protect your code from failure; you still need to catch exception. The question is more about what exceptions to catch and handle, and which ones should bubble upwards to the caller.

妖妓 2024-12-06 08:52:34

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

另请参阅我之前在这个问题中关于使用异常控制程序流的答案:

示例“使用异常来控制流程”

如下,我欢迎任何人自己尝试一下。人们谈论硬盘驱动器的主轴速度和访问时间 - 这是非常无关紧要的,因为我们没有计时。 OP询问完成他的任务最有效的方法是什么。正如您在这里所看到的那样,它是使用 File.Exists。这是可重复的。:

实际记录的性能结果:try/catch 与 File.Exists 对于不存在的文件

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

来源http://pastebin.com/6KME40md

结果:

RemoveLocalFiles1(try/catch):119ms

RemoveLocalFiles2(File.Exists):106ms

It's far better to do File.Exists first. Exceptions have a large overhead. In terms of efficiency, your definition isn't very clear, but performance and memory-wise, go for File.Exists.

See also my previous answer in this question about using Exceptions to control program flow:

Example of "using exceptions to control flow"

As below, I welcome anyone to try this themselves. People talking about spindle speed and access times for hard drives - that is massively irrelevant, because we are not timing that. The OP asked what the most performant way of achieving his task is. As you can see clear as day here, it's to use File.Exists. This is repeatable.:

Actual recorded performance results: try/catch vs File.Exists for non-existent files

Number of files (non-existent): 10,000

Source: http://pastebin.com/6KME40md

Results:

RemoveLocalFiles1 (try/catch) : 119ms

RemoveLocalFiles2 (File.Exists) : 106ms

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文