2015-09-28 104 views
2

我試圖只在文件存在時纔打開FileStream,否則做別的事情(不創建它,所以FileMode.OpenOrCreate不適用)。原子檢查一個文件是否存在並打開它

然而,簡單地創建FileStream不會阻止競爭條件爲FileStream,必須創建一個機會,在這種情況下FileNotFoundException將被拋出之前文件就可以刪除之前檢查File.Exists

有沒有辦法實現這個「原生地」,而不訴諸以下嘗試捕捉包裝:

/// <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; 
    } 
} 
+0

這種情況下try/catch包裝器有什麼問題? –

+1

這似乎是一個合適的解決方案。 File.Exist調用將處理大多數情況,捕獲將處理特例。 – Dennisch

回答

4

你可以使用P/Invoke來調用Windows API的CreateFile()函數打開該文件。如果文件無法打開,則返回空句柄(儘管您必須致電GetLastError()才能確定爲什麼文件無法打開)。

確保您使用CreateFile()在P/Invoke的聲明,它返回一個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 
); 

如果你這樣做,那麼你可以將句柄傳遞給the overload of the FileStream()構造函數接受SafeHandle

這是我們所「原生」,你會得到...

不過,我建議你剛剛捕獲異常。