在另一个进程写入文件时读取文件

时间:2013-03-13 12:26:02

标签: c++ windows file winapi createfile

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

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

它正确打开,没有错误。但是,当我从文件中读取数据时,似乎阻止了其他进程写入文件,因为我丢失了数据。

缓冲区是循环的,这意味着文件大小是固定的,并且新数据会不断写入缓冲区中的旧数据。

修改 有时最琐碎的解决方案有效......

我已经联系了该软件公司并告诉他们这个错误,并在一天之内发布了一个带有修复程序的新版本。 对不起,这对所有人都不起作用。

2 个答案:

答案 0 :(得分:4)

我建议查看优秀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()SetFilePointerExReadFile API调用eventually result。 OVERLAPPED未使用。

答案 1 :(得分:4)

如果不知道写作过程是如何打开文件的话,很难说出你的选择。显然,它不会打开文件进行独占访问并保持打开状态。否则你将无法阅读它。

您描述的行为表明写入过程打开文件以进行独占访问,写入文件,然后关闭文件。如果是这种情况,那么您无法让程序打开文件并保持打开状态。这会导致写入过程在尝试写入时失败。

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

您是否知道写入过程在无法打开文件时是丢失数据,还是只是缓冲数据并在下次实际打开文件时写入数据?如果是这种情况,那么我建议逐步浏览文件可能会有效。否则,你将丢失数据。

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

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