2013-03-13 55 views
3

我正在嘗試從不同的進程(我不能修改)連續寫入的緩衝區文件中讀取二進制數據。我使用的是爲了下面的代碼來打開文件:讀取正在被其他進程寫入的文件

fileH = CreateFileA((LPCSTR)filename, 
        GENERIC_READ, 
        FILE_SHARE_READ | FILE_SHARE_WRITE, 
        NULL, 
        OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, NULL); 

而且它沒有錯誤正確打開。但是,當我從文件中讀取數據時,似乎阻止其他進程寫入文件,因爲我丟失了數據。

緩衝區是循環的,這意味着文件大小是固定的,並且新數據不斷寫入緩衝區中較舊的數據。

編輯: 有時,最瑣碎的解決方案工作...

我已經聯繫這家軟件公司,並告訴他們有關的bug,並在一天之內,他們貼有一個修復的新版本。 對不起,這不適合每個人。

+2

同時讀寫一個文件是一個壞主意。嘗試使用'Mutex'或'Events'來處理訪問。 – 2013-03-13 12:29:22

+1

@ bash.d,真的嗎?告訴「尾巴」和類似的工具。您也無法使用互斥鎖和事件來同步進程。另外他說他不能修改其他應用程序。 – 2013-03-13 12:34:25

+0

@aleguna地獄,是的,你可以!閱讀第一行[這裏](http://msdn.microsoft.com/en-us/library/windows/desktop/ms686927(v = vs.85).aspx)。 – 2013-03-13 12:40:47

回答

3

我會建議看一下優秀的Far Manager的源代碼。它的內部查看器可以輕鬆處理多GB的文件,沒有任何問題顯示正在寫入的文件,並且幾乎可以實時更新已更改的文件內容。我從未注意到顯示的文件存在任何阻塞問題。

與該問題相關的源代碼似乎在viewer.cpp文件中。

一個有趣的事情是,它使用GENERIC_READ

ViewFile.Open(strFileName, FILE_READ_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, nullptr, OPEN_EXISTING); 

我懷疑下降SYNCHRONIZE可能是這裏重要的。

文件變化檢測是在Viewer::ProcessKeyKEY_IDLE情況:

// Smart file change check -- thanks Dzirt2005 
// 
bool changed = (
    ViewFindData.ftLastWriteTime.dwLowDateTime!=NewViewFindData.ftLastWriteTime.dwLowDateTime || 
    ViewFindData.ftLastWriteTime.dwHighDateTime!=NewViewFindData.ftLastWriteTime.dwHighDateTime || 
    ViewFindData.nFileSize != NewViewFindData.nFileSize 
); 
if (changed) 
    ViewFindData = NewViewFindData; 
else { 
    if (!ViewFile.GetSize(NewViewFindData.nFileSize) || FileSize == static_cast<__int64>(NewViewFindData.nFileSize)) 
     return TRUE; 
    changed = FileSize > static_cast<__int64>(NewViewFindData.nFileSize); // true if file shrank 
} 

緩存文件讀出在cache.cpp實現。但沒有什麼東西真的讓人震驚,只有一些Seek()Read()(即eventually result,SetFilePointerExReadFile API調用)。不使用重疊。

+0

如果它可以查看由另一個進程在獨佔模式下打開的文件,我會很驚訝。 – 2013-03-13 14:40:29

+0

當然,它不適用於專門打開的文件。但我沒有發現它很常見,尤其是對於日誌文件。 – 2013-03-13 15:21:27

4

如果不知道寫入過程如何打開文件,很難說出您的選擇。顯然,它不打開文件進行獨佔訪問並保持打開狀態。否則,你根本無法讀取它。

您描述的行爲表示寫入過程打開文件進行獨佔訪問,寫入文件,然後關閉文件。如果是這種情況,那麼你不能讓你的程序打開文件並保持打開狀態。這會導致寫入過程在嘗試寫入時失敗。

如果你不能修改寫作過程,那麼你的選擇是有限的,不是很有吸引力。最有可能的是,您必須讓程序打開文件,讀取一小塊文件,關閉文件,然後等待一會再讀取。即使如此,也不能保證寫入過程試圖寫入時不會打開文件。我認爲,你已經發現了。

是否知道寫入過程在無法打開文件時是否會丟失數據,或者只是緩存數據並在下次真正打開文件時寫入數據?如果是這樣的話,那麼我一次一點一點地瀏覽文件的建議可能會奏效。否則,你將失去數據。

沒有開放模式,我知道這相當於「打開文件進行閱讀,但如果有人想要獨佔訪問,那麼讓他們擁有它。」

另一種可能性是讓您的程序在您想要讀取時重命名該文件,然後在讀取它之後刪除重命名的文件。當然,這假定寫作過程將在必要時創建一個新文件。即使如此,如果編寫過程在重命名時嘗試寫入,可能會出現問題。我認爲這不會是一個問題(就文件系統而言,重命名可能是原子的),但這是你必須研究的問題。

+0

數據在寫入過程中真的丟失了,所以即使在非常短的時間內打開文件也會導致此損失。重命名文件聽起來像是一個有趣的可能性,我會檢查它。 – user1447407 2013-03-14 07:42:43

相關問題