不使用try catch如何检查文件是否正在使用?

13

有没有一种方法可以检查文件是否正在使用或是否未被其他进程打开,而不仅仅是尝试打开它并捕获异常? 是否没有服务方法来测试这种情况?


6
好的,为什么你想知道呢?为了之后打开文件吗?那么你可以直接跳过检查并尝试打开,因为你可能无论如何都会遇到竞态条件。 - Joey
@Јοеу并不是必须的,但通常情况下这是原因。一旦涉及到第三方工具,确定文件是否可以被打开再调用第三方的打开方法会很有帮助。无论如何,我期望会有这样的方法,而不是将catch语句作为计划的一部分来实现。 - CloudyMarble
可能是一个重复的问题: 如何在C语言中检查文件是否已被另一个进程打开? - David Heffernan
这不是重复的,主要点在于尝试使用try catch,而不是一般性地是否可能。 - CloudyMarble
如果Hal的C答案(非标记为答案的那个)与David提供的链接相符,则你可以在这里找到.NET P/Invoke IsFileInUse等效版本:http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/dead0507-06f5-43e0-9250-a78437956bc8 - Simon Mourier
4个回答

15
即使有这样的功能,也不会对您有太大好处,因为您仍然需要捕获异常以处理在初始检查和实际尝试打开/访问文件之间出现文件不可用的竞态条件。
我想不到任何初步防御性检查的明显优势。它只会导致不必要的代码重复。
如果存在这样一个IsFileAccessible函数,它可能会被实现为一个巨大的try/catch块,尝试打开文件,捕获失败并返回结果。

1
你是对的。但是,虽然你不能避免在最后检查异常,但拥有一个检查异常的函数而不必打开文件仍然是有趣的。一些有用的工具可以提供这些信息,它们并不基于try/catch代码。 - Simon Mourier
@Simon 因为我认为问题的本质并不是关于异常。我的理解是“我能否在尝试打开文件之前测试它是否可以被打开?”我认为错误处理机制并不是重点。 - David Heffernan
1
无论您是否捕获异常都不重要。关键是要实际尝试打开文件才能知道是否可以打开它。在异常被发明之前(并且仍然在不支持异常的语言中),OpenFile函数(或等效函数)只返回指示成功或特定错误条件的错误代码:FileNotFoundFileInUseUnauthorizedAccess等。@two - Cody Gray
最佳实践是在异常情况下抛出异常。我认为应该检查文件是否可访问,然后打开它,但仍然需要一个catch块来处理在检查和实际打开之间条件发生变化的情况。 - jaraics
@jar 冗余代码更难维护。你只会让自己的生活更加困难。这样想:在这两种情况下,你会有不同的反应吗?我无法想象为什么会有。无论如何,文件都无法打开。关键是,既然你必须* anyway *处理错误/异常,为什么要让自己的事情变得更加困难呢? - Cody Gray
显示剩余7条评论

3

我能否在不尝试打开它的情况下测试文件是否可以被打开?

就像底层的Windows API一样,.NET框架也没有提供这样的功能。如果你想知道一个文件是否可以被打开,你需要尝试打开它并检查是否失败。


0

避免使用try catch的有趣方法(但意味着尝试打开)是使用LockFile()CreateFile()函数:

HANDLE WINAPI CreateFile(...)

如果函数成功,则返回值是指向指定文件、设备、命名管道或邮件槽的打开句柄。

如果函数失败,则返回值为INVALID_HANDLE_VALUE。要获取扩展错误信息,请调用GetLastError


BOOL WINAPI LockFile(...)

如果函数成功,返回值为非零(TRUE)。

如果函数失败,返回值为零(FALSE)。要获取扩展错误信息,请调用GetLastError

这将锁定指定的文件以供调用进程独占访问,并在失败时将错误信息写入线程的上一个错误中,可以使用GetLastError函数检索该信息。

仍有可能在unlockFile和OpenFile之间的时间内另一个进程锁定文件,但可以通过仅在需要打开文件的时刻保持文件被锁定来最小化此时间。


1
问问自己hFile来自哪里? - David Heffernan
你是对的!我最终使用了CreateFile,虽然它不会抛出异常并且允许可读的返回值,但它仍然是打开文件的一种尝试。 - CloudyMarble
1
这正是我和其他人一直在告诉你的。恰好,.net打开文件的机制通过异常来标志失败。Win32机制通过返回值来标志错误。从根本上讲,最终结果是相同的。 - David Heffernan
@DavidHeffernan 嗯,有些人需要走一条漫长的路才能理解它,谢谢。但是,.net不能运行所有进程以检查是否有任何进程锁定文件,并将其作为文件功能提供吗?我有什么遗漏吗? - CloudyMarble
Windows没有提供除尝试打开文件之外的机制来完成这个任务。 - David Heffernan
1
@TwoMore 或许操作系统可以这样做(尽管像David所说,它并没有这样做),但正如我在我的回答中解释的那样,如果它这样做了,它将不会有任何有用的目的。像这样的代码:if (FileExists(file)) { OpenFile(file); }基本上有缺陷的,因为它没有处理文件在调用FileExists()OpenFile()之间消失的情况。因此,您可能想要尝试打开文件并处理任何错误(无论是来自异常还是返回代码)。我的回答讨论了异常,因为您在问题中应用了标签。 - Cody Gray

0

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