2010-07-22 62 views
0

我有一種方法,它使用二進制打字機寫一個記錄組成的幾個提示和一個字節數組到文件。作爲我的程序的一部分,此方法每秒執行十幾次。代碼如下:二進制打字機不打開文件在流結束

iLogFileMutex.WaitOne(); 
using (BinaryWriter iBinaryWriter = new BinaryWriter(File.Open(iMainLogFilename, FileMode.OpenOrCreate, FileAccess.Write))) 
{ 
    iBinaryWriter.Seek(0, SeekOrigin.End); 
    foreach (ViewerRecord vR in aViewerRecords) 
    { 
     iBinaryWriter.Write(vR.Id); 
     iBinaryWriter.Write(vR.Timestamp); 
     iBinaryWriter.Write(vR.PayloadLength); 
     iBinaryWriter.Write(vR.Payload);   
    } 
}  
iLogFileMutex.ReleaseMutex(); 

上面的代碼工作正常,但如果我刪除與尋求通話線路,產生的二進制文件已損壞。例如,某些記錄完全丟失,或者其中的一部分不存在,儘管絕大多數記錄都寫得很好。所以我想象錯誤的原因是當我反覆打開和關閉文件時,文件中的當前位置並不總是在末尾,事情會被覆蓋。

所以我的問題是:爲什麼不是C#確保當前位置在最後打開文件時?

PS:我從如果要追加到文件造成這個錯誤

回答

1

問題是FileMode.OpenOrCreate和ViewerRecord成員類型的組合。其中一個或多個不是固定大小的類型,可能是一個字符串。

當文件已經存在時事情就出錯了。您將開始在文件開始處寫入數據,覆蓋現有數據。但是你寫的只是偶然地覆蓋現有的記錄,字符串必須是完全相同的大小。如果你沒有寫足夠的記錄,那麼你將不會覆蓋所有的舊記錄。當你閱讀文件時會遇到麻煩,你會在閱讀最後一個書面記錄後閱讀舊記錄的一部分。你會得到一段時間的垃圾。

將記錄製作成固定大小並不能真正解決問題,您會看到一個很好的記錄,但它會是一箇舊記錄。你會得到哪一組特定的舊記錄取決於你寫了多少新數據。這應該與讀取亂碼數據一樣糟糕。

如果您確實需要保留舊記錄,那麼您應該追加到文件FileMode.Append。如果你不這樣做,你應該重寫文件FileMode.Create。

+0

解釋一下,歡呼:) – CalumMcCall 2010-07-22 16:38:34

4

排除線程問題,您必須在打開調用中使用FileMode.Append,否則文件將其位置設置爲打開文件的開始,而不是結束。

+0

很確實,我應該在我的帖子中指出這一點。然而,爲什麼我仍然會得到大量的記錄,包括第一個記錄,沒有任何問題,然後在文件的中間位置,我記錄了一半的記錄,然後它們也很好。追加還是缺乏,不會造成這種情況呢?當然,我只應該得到實際存在於文件中的最後一個記錄列表? – CalumMcCall 2010-07-22 15:25:39

+0

那麼你發佈的代碼實際上並不是有問題的代碼? – 2010-07-22 15:41:46