C++ 在另一进程写入文件时读取该文件

C++ 在另一进程写入文件时读取该文件,c++,windows,file,winapi,createfile,C++,Windows,File,Winapi,Createfile,我试图从一个缓冲区文件中读取二进制数据,该文件由另一个进程连续写入(我无法修改)。我使用以下代码打开文件: fileH = CreateFileA((LPCSTR)filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,

我试图从一个缓冲区文件中读取二进制数据,该文件由另一个进程连续写入(我无法修改)。我使用以下代码打开文件:

fileH = CreateFileA((LPCSTR)filename,
                    GENERIC_READ,
                    FILE_SHARE_READ | FILE_SHARE_WRITE,
                    NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL, NULL);
它可以正确地打开,没有错误。但是,当我从文件中读取数据时,它似乎会阻止其他进程写入文件,因为我丢失了数据

缓冲区是循环的,这意味着文件大小是固定的,新数据不断地写在缓冲区中较旧的数据上

编辑: 有时候,最简单的解决方案是有效的

我已经联系了软件公司,告诉他们这个错误,一天之内,他们发布了一个新版本,并进行了修复。
很抱歉,这不能适用于所有人。

我建议您查看优秀的源代码。它的内部查看器可以轻松处理数千GB的文件,显示正在写入的文件没有问题,并且几乎可以实时更新更改的文件内容。我从未注意到显示的文件有任何阻塞问题

与该问题相关的源代码似乎在该文件中

一件有趣的事情是它没有使用
泛型\u READ

ViewFile.Open(strFileName, FILE_READ_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, nullptr, OPEN_EXISTING);
我怀疑删除
SYNCHRONIZE
在这里可能很重要

文件更改检测在
Viewer::ProcessKey
KEY\u 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
}
//智能文件更改检查——谢谢Dzirt2005
//
布尔更改=(
ViewFindData.ftLastWriteTime.dwLowDateTime!=新ViewFindData.ftLastWriteTime.dwLowDateTime||
ViewFindData.ftLastWriteTime.dwHighDateTime!=NewViewFindData.ftLastWriteTime.dwHighDateTime||
ViewFindData.nFileSize!=新建ViewFindData.nFileSize
);
如果(更改)
ViewFindData=NewViewFindData;
否则{
如果(!ViewFile.GetSize(NewViewFindData.nFileSize)| | FileSize==static_cast(NewViewFindData.nFileSize))
返回TRUE;
changed=FileSize>static_cast(NewViewFindData.nFileSize);//如果文件收缩,则为true
}

缓存文件读取在中实现。但是那里没有什么真正惊天动地的东西,只有一些
Seek()
Read()
(在
SetFilePointerEx
ReadFile
API调用中)。不使用重叠。

在不知道写入过程如何打开文件的情况下,很难说出您的选项。显然,它不是以独占方式打开文件并保持打开状态。否则你根本看不懂

您描述的行为表明,写入过程以独占方式打开文件、写入文件,然后关闭文件。如果是这样的话,那么你就不能让你的程序打开文件并保持打开状态。这将导致写入过程在尝试写入时失败

如果你不能修改写作过程,那么你的选择是有限的,也不是很有吸引力。最有可能的情况是,您必须让程序打开文件,读取一小块,关闭文件,然后等待一段时间再读取。即使这样,也不能保证在写入过程尝试写入时不会打开文件。我想你已经发现了

您知道写入过程在无法打开文件时是否会丢失数据,或者它只是缓冲数据并在下次实际打开文件时写入数据吗?如果是这样的话,那么我的建议是一次浏览一点文件就行了。否则,您将丢失数据

据我所知,没有一种开放模式相当于“打开文件进行阅读,但是如果有人想要独占访问,那么就让他们拥有它。”


另一种可能是让您的程序在您想读取文件时重命名该文件,然后在读取后删除重命名的文件。当然,这假设在必要时,写入过程将创建一个新文件。即使如此,如果编写过程在重命名时尝试写入,也可能会出现问题。我不认为这会是一个问题(就文件系统而言,重命名可能是原子的),但这是您必须研究的问题。

同时从/向文件读写是一个坏主意。尝试使用
Mutex
Events
来处理访问。@bash.d,真的吗?告诉
tail
和类似的实用程序。此外,您不能使用互斥体和事件来同步进程。此外,他还说他不能修改其他应用程序。真正的问题是为什么在2013年你仍然使用非Unicode API。你是说
CreateFileW
?你知道另一个进程是保持文件打开,还是每次需要写入时都试图打开文件?如果它试图以独占模式打开文件,当您打开该文件进行读取时,它将失败。与其他人所说的相反,一般来说,让多个进程读/写同一个文件是完全可以的。太本地化了吗?说真的?如果它可以查看另一个进程以独占模式打开的文件,我会非常惊讶。当然,它不能处理以独占模式打开的文件。但我发现这种情况并不常见,尤其是对于日志文件。在编写过程中,数据确实会丢失,所以即使在很短的时间内打开文件,也会导致这种丢失。重命名文件听起来很有可能,我会检查一下。