2011-01-20 44 views
3

我有一個程序需要在寫入目錄後立即從目錄加載文件。我得到了FileSystemWatcher來通知我對目錄的更改。而不是檢查事件是否發生了變化,我只列出這些文件並開始處理所有發現的內容。在寫入文件之後立即讀取文件我得到全零(.net)

爲了防止嘗試讀取它仍然被寫入我有這樣的代碼文件:

try { 
    fs = fi.Open(FileMode.Open, FileAccess.ReadWrite, 
        FileShare.None); 
    message = new byte[fs.Length]; 
    int br = fs.Read(message, 0, (int)fi.Length); 
} 
catch (Exception e) { 
    // I'll get it next time around 
    return; 
} 
finally { 
    if (fs != null) 
     fs.Close(); 
} 

的問題是,對於某些文件,在200約1時,程序讀取全部爲零。文件長度是正確的,但內容看起來都是零字節。當我檢查後面的文件時,我發現它確實包含實際的正確數據。我認爲我打開文件的方式可以防止過早訪問文件。

我使用DOS命令'copy InFile_0 * dropdir'(每次執行大約100個文件)將文件複製到目錄中進行測試。可能此命令在兩個步驟中執行副本:1)分配空間和2)填充空間和我的程序偶爾會跳到兩個中間。

有關如何對此進行編碼以確保可靠性的任何想法?

更新:我無法控制寫程序 - 它可能是任何東西。看起來我必須防守編碼。

+1

提示:爲您的異常添加日誌記錄。不要默默地失敗。 – Amy 2011-01-20 00:03:32

+0

您正在使用不會對該文件施加任何鎖定的程序。例如,對於C程序來說通用,fopen()允許任何程序在文件打開時讀寫。贏得超越「等待一段時間」的方式並不多。 – 2011-01-20 01:20:43

回答

2

您遇到了競爭條件。除非你明確地修復它,否則它只會從這裏變得更糟(使用網絡文件系統等)。

嘗試讓程序編寫文件,使用「whatever.tmp」名稱編寫每個文件,然後關閉它,然後重命名它。閱讀時,忽略.tmp文件。

或者,在目錄中保留一個名爲「sentinel」的零長度文件或一些這樣的文件。在每次成功寫入另一個文件後,讓程序編寫文件以重寫哨兵文件。然後,請勿嘗試讀取修改日期/時間> =修改日期/時間的文件。

或者,如果您無法控制文件的作者,請根據當前系統日期/時間檢查每個文件的修改日期/時間。在嘗試閱讀文件之前,讓文件的年齡適當(如果他們小的話幾秒鐘,如果他們更大的話會長一點)。

祝你好運。這是脖子上臭名昭着的痛苦。

1

嗯,我不同意@Ollie Jones之前的帖子。

您已經建立了對文件的獨佔訪問權限,所以沒有競態條件問題。

我想你應該更仔細地檢查作者的行爲。並儘量減少與只讀文件訪問的干擾,共享所有訪問:

fi.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 

這可能會失敗,你的讀操作,但會降低寫入錯誤。要決定何時安全閱讀,您可以檢查文件時間或文件大小等。如果隨後會寫入很多文件,則可以在創建第二個文件後開始讀取第一個文件。