2013-03-13 234 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

相关问题