自动检查文件是否存在并打开它

Atomically check if a file exists and open it

我试图仅在文件存在时打开 FileStream,否则执行其他操作(不创建它,因此 FileMode.OpenOrCreate 不适用)。

但是,在创建 FileStream 之前简单地检查 File.Exists 不会阻止竞争条件,因为文件可能会在 FileStream 有机会创建之前被删除,在这种情况下FileNotFoundException 将被抛出。

有没有一种方法可以实现此 "natively",而无需诉诸以下 try catch 包装器:

/// <returns>false if the file does not exists, true otherwise.</returns>
public static bool TryOpenFileStreamIfExists(string filePath, FileAccess fileAccess, FileShare fileShare, out FileStream fs, FileOptions fileOptions = FileOptions.None) {
    try {
        if (!File.Exists(filePath)) {
            fs = null;
            return false;
        }
        fs = new FileStream(filePath, FileMode.Open, fileAccess, fileShare, short.MaxValue, fileOptions);
        return true;
    }
    catch (FileNotFoundException) {
        fs = null;
        return false;
    }
}

您可以使用P/Invoke调用WindowsAPI的CreateFile()函数来打开文件。如果文件无法打开,此 returns 为空句柄(尽管您必须调用 GetLastError() 来确定 为什么 文件无法打开).

确保对 CreateFile() 使用 P/Invoke 声明,其中 returns 和 SafeHandle,例如:

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern SafeFileHandle CreateFile
(
    string lpFileName,
    [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
    [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
    IntPtr lpSecurityAttributes,
    [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
    [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
    IntPtr hTemplateFile
);

如果这样做,则可以将句柄传递给接受 SafeHandle.

the overload of the FileStream() 构造函数

这与您将获得的 "native" 差不多...

但是,我建议您只捕获异常。