如何确定文件在删除前是否正在使用?

5
我正在编写一个Windows服务,可能会在某个时刻删除文件。由于服务涉及常规文件IO,因此在删除期间文件可能正在使用。
目前,我尝试先删除文件,然后在出现异常时再进行处理。代码大致如下:
try
{
    File.Delete(file);
    Status = ResponseStatus.Ok;
}
catch (IOException e)
{
    Status = ResponseStatus.FileInUse;
}
finally
{
    return Status;
}

如何在不使用异常的情况下确定文件是否正在使用?


1
你目前的方法有什么问题? - P.K
@PK,我不确定这是否是最佳解决方案。我决定向大众求助,结合大家的智慧一定能找到最好的解决方法。 - Vadim
@PK:他目前的方法(删除并查看是否失败)的想法是正确的,但他不一定要在这里使用“异常”。如果他正在处理许多文件,则基于“异常”的方法的开销可能很大。导入“DeleteFile”应该更快,因为他仍然可以检查成功,但不会被卸载堆栈等开销所拖累。 - Adam Robinson
4个回答

13

试图事先检测文件是否正在使用是没有意义的 - 如果有人在您的检测代码和删除代码之间打开该文件,那该怎么办?您仍然需要现有的代码来处理这种情况。

您已经拥有的代码正是处理这种情况的正确方式。


4
如Richie所说,捕获异常可能是最佳方法。
但是,如果您想删除10个文件,并且不希望在中途失败怎么办?您确实需要一种保护整个事务的方式。因此,能够被动检查文件是否正在使用是有用的。您可以尝试打开文件进行写入(然后立即关闭),以确定文件是否正在使用(或只读,这也会使其无法删除)。但这本身并不能保证随后的删除尝试将成功。
其他可行的方法包括: - 在删除之前移动/重命名文件(将它们放在安全位置,以便您知道它们不会被另一个进程打开),以便如果任何单个移动操作失败,您可以“撤消”事务。 - 捕获异常并排队等待将来尝试删除文件(在您自己的程序中,或者您可以标记文件以在下次重新启动时由Windows自动删除)。

+1. 记住这点很好。然而,在我的情况下并不适用。该服务将一次删除一个文件。 - Vadim

3

如果你只是想测试删除是否成功而不捕获异常,那么你只需要声明一个DeleteFile函数的P/Invoke。

[DLLImport("Kernel32.dll", SetLastError = true)]
public static extern bool DeleteFile(string fileName);

如果删除成功,这将返回true,如果删除失败,则返回false。如果您想要特定的错误代码,可以调用Marshal.GetLastWin32Error()


3

在Richie正确的回答上进行扩展

当使用文件系统时,您永远无法可靠地确定操作是否成功。你所能做的只是尝试一次操作,然后检查它是否成功了。

文件系统是一个移动的目标,您对其没有控制权。许多外部和其他用户事件可以影响您无法控制的文件系统。在许多方面,它就像没有同步的多线程编程。每当您看到以下代码时,都会有一个微妙的错误

if (File.SomeTypeOfCheck(somePath) {
  File.DoSomeOperation(somePath);
}

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