基本上,我想在实际尝试打开文件之前检查是否有权打开文件; 除非必须,否则我不想使用try/catch进行此检查.有没有我可以检查的文件访问属性?
我过去曾做过无数次这样的事情,而且几乎每次我都这样做,我甚至做错了.
文件权限(甚至文件存在)是易变的 - 它们可以随时更改.感谢Murphy定律,这尤其包括检查文件和尝试打开文件之间的短暂时间.如果您位于您知道需要先检查的区域,则更有可能进行更改.但奇怪的是,它永远不会发生在您的测试或开发环境中,而这些环境往往是相当静态的.这使得问题很难在以后跟踪,并使这种错误很容易使其投入生产.
What this means is that you still have to be able to handle the exception if file permissions or existence are bad, in spite of your check. Exception handling code is required, whether or not you check for the permissions of the file in advance. Exception handling code provides all of the functionality of existence or permissions checks. Additionally, while exception handlers like this are known to be slow, it's important to remember that disk i/o is even slower... a lot slower... and calling the .Exists() function or checking permissions will force an additional trip out the file system.
总之,在尝试打开文件之前进行初始检查既冗余又浪费.与异常处理相比没有额外的好处,它实际上会伤害您的性能,而不是帮助,它会增加必须维护的代码的成本,并且可能会在您的代码中引入细微的错误.初步检查没有任何好处.相反,这里正确的做法是尝试打开文件,如果失败则将您的努力投入到良好的异常处理程序中.即使您只是检查文件是否存在,情况也是如此.这种推理适用于任何易变资源.
对于遇到类似问题的其他人来说,快速提示:
注意DropBox等Web同步应用.我只花了2个小时思考.NET中的"使用"语句(Dispose模式).
我最终意识到Dropbox不断在后台读取和写入文件,以便同步它们.
猜猜我的Visual Studio Projects文件夹位于何处?当然在"我的Dropbox"文件夹里面.
因此,当我在调试模式下运行我的应用程序时,DropBox也不断访问它正在读取和写入的文件,以便与DropBox服务器同步.这导致锁定/访问冲突.
所以至少我现在知道我需要一个更强大的文件打开功能(即TryOpen()将进行多次尝试).我很惊讶它不是框架的内置部分.
[更新]
这是我的助手功能:
////// Tries to open a file, with a user defined number of attempt and Sleep delay between attempts. /// /// The full file path to be opened /// Required file mode enum value(see MSDN documentation) /// Required file access enum value(see MSDN documentation) /// Required file share enum value(see MSDN documentation) /// The total number of attempts to make (multiply by attemptWaitMS for the maximum time the function with Try opening the file) /// The delay in Milliseconds between each attempt. ///A valid FileStream object for the opened file, or null if the File could not be opened after the required attempts public FileStream TryOpen(string filePath, FileMode fileMode, FileAccess fileAccess,FileShare fileShare,int maximumAttempts,int attemptWaitMS) { FileStream fs = null; int attempts = 0; // Loop allow multiple attempts while (true) { try { fs = File.Open(filePath, fileMode, fileAccess, fileShare); //If we get here, the File.Open succeeded, so break out of the loop and return the FileStream break; } catch (IOException ioEx) { // IOExcception is thrown if the file is in use by another process. // Check the numbere of attempts to ensure no infinite loop attempts++; if (attempts > maximumAttempts) { // Too many attempts,cannot Open File, break and return null fs = null; break; } else { // Sleep before making another attempt Thread.Sleep(attemptWaitMS); } } } // Reutn the filestream, may be valid or null return fs; }