9

我有一个应用程序,有时我需要从正在写入的文件中读取并因此被锁定。正如我从其他问题中了解到的那样,我应该捕获 IOException 并重试,直到我可以阅读为止。

但我的问题是我如何确定该文件已被锁定并且它不是另一个 IOExcetpion 发生。

4

6 回答 6

6

当您打开文件以在 .NET 中读取时,它会在某个时候尝试使用CreateFile API 函数创建文件句柄,该函数设置错误代码,可用于查看失败的原因:

const int ERROR_SHARING_VIOLATION = 32;
try
{
    using (var stream = new FileStream("test.dat", FileMode.Open, FileAccess.Read, FileShare.Read))
    {
    }
}
catch (IOException ex)
{
    if (Marshal.GetLastWin32Error() == ERROR_SHARING_VIOLATION)
    {
        Console.WriteLine("The process cannot access the file because it is being used by another process.");
    }
}
于 2009-03-27T16:06:58.753 回答
4

有一个关于谷歌群组的有用讨论,你真的应该阅读。其中一个选项接近达林的;然而,为了保证你得到正确的 win32 错误,你真的应该自己调用 win32 OpenFile() API(否则,你真的不知道你正在检索哪个错误)。

另一个是解析错误消息:如果您的应用程序在其他语言版本上运行,这将失败。

第三种选择是通过反射破解异常类以找出实际的 HRESULT。

没有一个替代品真的那么有吸引力:IOException 层次结构将受益于更多的子类恕我直言。

于 2009-03-27T16:11:23.657 回答
0

要读取数据,您可以执行以下操作:

使用 (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) { .... }

并保存到文件中:

使用 (FileStream fs = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.Read | FileShare.Delete)) { ... }

构造函数末尾的标志描述了其他进程可以对文件执行的操作。当然,如果您同时控制写入和读取,那也没关系...

于 2009-03-27T15:45:01.897 回答
0

您可以与 IOException 类型进行比较以检查它是否不是别的东西

if (ex is FileNotFoundException)

您可能想查找有关 System.IO 的帮助。该类中的许多异常都继承自IOException。除了检查它是否是另一种类型的异常之外,您可能必须查看描述消息,或者您可能会考虑对 shell32.dll 进行 Win32 API 调用。那里可能有一个功能可以检查文件是否被锁定。

此外,如果您绝对需要等待,您可以使用循环,但如果您想在等待时执行其他操作,请使用异步线程。

于 2009-03-27T15:45:47.230 回答
0

您可以打开它(如 bezieur 所述)然后尝试锁定部分(或整个文件): http ://www.java2s.com/Code/VB/File-Directory/Lockandunlockafile.htm

于 2009-03-27T15:54:54.180 回答
0

你的意思是你正在读取和写入文件?或者外部应用程序正在写入它。

如果您正在读取和写入,那么我假设您是在不同的线程上执行此操作,在这种情况下,请查看 ReaderWriteLock 类,该类将为您执行此管理,并允许您提供超时。

http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlock.aspx

否则,您需要做的就是以只读模式打开文件。那么你应该没有任何问题:

fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read));
于 2009-03-27T15:59:13.330 回答