use*_*407 6 c++ windows winapi file createfile
我正在尝试从缓冲区文件中读取二进制数据,该文件由不同的进程(我无法修改)连续写入.我正在使用以下代码打开文件:
fileH = CreateFileA((LPCSTR)filename,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
Run Code Online (Sandbox Code Playgroud)
它正确打开,没有错误.但是,当我从文件中读取数据时,它似乎阻止了其他进程写入文件,因为我丢失了数据.
缓冲区是循环的,这意味着文件大小是固定的,并且新数据会不断写入缓冲区中的旧数据.
编辑: 有时最琐碎的解决方案有效......
我已经联系了这家软件公司并告诉他们这个bug,并在一天之内发布了一个带有修复程序的新版本.对不起,这不适用于所有人.
我建议查看优秀的Far Manager的源代码。其内部查看器可以轻松处理数千兆字节的文件,可以毫无问题地显示正在写入的文件,并且可以几乎实时更新更改的文件内容。我从未注意到显示的文件有任何阻塞问题。
与问题相关的源代码似乎位于viewer.cpp文件中。
一件有趣的事情是它不使用GENERIC_READ:
ViewFile.Open(strFileName, FILE_READ_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, nullptr, OPEN_EXISTING);
Run Code Online (Sandbox Code Playgroud)
我怀疑掉落SYNCHRONIZE在这里可能很重要。
文件更改检测在Viewer::ProcessKey,KEY_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
}
Run Code Online (Sandbox Code Playgroud)
缓存文件的读取在cache.cpp中实现。但那里并没有什么真正惊天动地的事情,只是一些Seek()and Read()(最终导致and SetFilePointerExAPIReadFile调用)。不使用重叠。
在不知道写入过程如何打开文件的情况下很难说出您的选择。显然,它不会打开文件以进行独占访问并保持打开状态。否则,您将根本无法阅读。
您描述的行为表明写入过程打开文件以进行独占访问,对其进行写入,然后关闭该文件。如果是这种情况,那么您将无法使程序打开文件并保持打开状态。每当尝试写入时,这都会导致写入过程失败。
如果您无法修改写作过程,那么您的选择将是有限的,而且不会很吸引人。最有可能的是,您必须使程序打开文件,读取一小块,关闭文件,然后稍等片刻,然后再次读取。即使这样,也无法保证在写入过程尝试进行写入时不会打开文件。我认为您已经发现了。
您是否知道写入过程无法打开文件时丢失了数据,还是只是缓冲了数据并在下次可以实际打开文件时写入了数据?如果是这种情况,那么我建议一点一点地逐步遍历该文件可能会起作用。否则,您将丢失数据。
我知道没有一种打开模式等效于“打开文件以进行读取,但是如果有人想要独占访问,则让他们拥有它。”
另一种可能性是让您的程序在每次要读取的时候重命名文件,然后在读取文件后将其删除。当然,这假设写入过程将在必要时创建一个新文件。即使这样,如果在重命名时写入过程尝试写入,也可能会出现问题。我认为这不会成为问题(就文件系统而言,重命名可能是原子的),但这是您必须研究的内容。
| 归档时间: |
|
| 查看次数: |
11783 次 |
| 最近记录: |