簡體   English   中英

在另一個進程寫入文件時讀取文件

[英]Reading a File while it is being written by another process

我正在嘗試從緩沖區文件中讀取二進制數據,該文件由不同的進程(我無法修改)連續寫入。 我正在使用以下代碼打開文件:

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

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

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

編輯:有時最瑣碎的解決方案有效......

我已經聯系了這家軟件公司並告訴他們這個bug,並在一天之內發布了一個帶有修復程序的新版本。 對不起,這不適用於所有人。

如果不知道寫入過程是如何打開文件的話,很難說出你的選擇。 顯然,它不會打開文件進行獨占訪問並保持打開狀態。 否則你將無法閱讀它。

您描述的行為表明寫入過程打開文件以進行獨占訪問,寫入文件,然后關閉文件。 如果是這種情況,那么您無法讓程序打開文件並保持打開狀態。 這會導致寫入過程在嘗試寫入時失敗。

如果你不能修改寫作過程,那么你的選擇是有限的,不是很有吸引力。 最有可能的是,你必須讓程序打開文件,讀取一小塊文件,關閉文件,然后再等一會兒再讀一遍。 即使這樣,也無法保證在寫入過程嘗試寫入時您不會打開文件。 我想,你已經發現了。

您是否知道寫入過程在無法打開文件時是丟失數據,還是只是緩沖數據並在下次實際打開文件時寫入數據? 如果是這種情況,那么我建議逐步瀏覽文件可能會有效。 否則,您將丟失數據。

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

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

我建議查看優秀遠程經理的源代碼。 它的內部查看器可以輕松處理數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()最終導致 SetFilePointerExReadFile API調用)。 OVERLAPPED未使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM