刷新不调用文件更改
Flush not invoking file change
我正在编写一个程序,其中一个进程 A 读取另一个进程 B 附加到文件的数据。问题是,尽管我使用 fflush 将内容刷新到文件,但在我关闭 B 中的句柄之前不会生成通知。代码如下
文件编写器:
int _tmain(int argc, _TCHAR* argv[])
{
FILE *fp;
fp=_fsopen("log.txt", "a", _SH_DENYNO);
char str[4096];
for(int i=1;i<4096;i++)
str[i]=i;
while(true){
fwrite(str,1,4096,fp);
fflush(fp);
Sleep(2000);
}
return 0;
}
文件读取器:
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
#include <conio.h>
#include <assert.h>
#include <share.h>
void _tmain(int argc, TCHAR *argv[])
{
FILE *fp;
fp=_fsopen("C:\Users\dell\Documents\Visual Studio 2012\Projects\FileWriter\FileWriter\log.txt", "r", _SH_DENYNO);
int last_size=0,new_size=0;
if(fp==NULL)
return ;
HANDLE m_hMonitoredDir = CreateFile(TEXT("C:\Users\dell\Documents\Visual Studio 2012\Projects\FileWriter\FileWriter"), FILE_LIST_DIRECTORY,
FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL );
if ( m_hMonitoredDir == INVALID_HANDLE_VALUE )
{
DWORD dwErr = GetLastError();
printf("error");
return;
}
char szBuf[ MAX_PATH ];
DWORD dwBytesRead = 0;
int flag=0;
char *buffer;
while ( ReadDirectoryChangesW( m_hMonitoredDir, szBuf, MAX_PATH, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE,&dwBytesRead, NULL, NULL ))
{
PFILE_NOTIFY_INFORMATION pstFileNotif = (PFILE_NOTIFY_INFORMATION)( szBuf );
if ( pstFileNotif->Action == FILE_ACTION_MODIFIED )
{
char szNotifFilename[ MAX_PATH ] = { 0 };
if ( int iNotifFilenameLen = WideCharToMultiByte( CP_OEMCP, NULL,
pstFileNotif->FileName,
pstFileNotif->FileNameLength / sizeof( WCHAR ),
szNotifFilename, sizeof( szNotifFilename ) / sizeof( char ),
NULL, NULL ) )
{
if ( strcmp("log.txt", szNotifFilename ) == 0 )
{
fseek(fp, 0, SEEK_END);
new_size = ftell(fp);
fseek(fp,last_size,SEEK_SET);
int size=new_size-last_size;
buffer=new char[size+1];
fread(buffer,1,size,fp);
buffer[size]=' ';
printf("%s",buffer);
free(buffer);
}
}
}
}
}
任何人都可以帮助我在 B 中使用 fflush 后立即收到通知吗?
我认为这是不可能的。 根据有关FILE_NOTIFY_CHANGE_LAST_WRITE
的文档(强调我的(:
对监视目录或子树中文件的上次写入时间的任何更改都会导致返回更改通知等待操作。仅当文件写入磁盘时,操作系统才会检测到上次写入时间的更改。对于使用大量缓存的操作系统,仅当缓存充分刷新时,才会进行检测。
fflush()
确保将文件数据传递回操作系统,但不能保证将数据写入磁盘,因为通常涉及大量缓存:
缓冲区通常由操作系统维护,操作系统确定将数据自动写入磁盘的最佳时间:缓冲区已满、流关闭或程序正常终止而不关闭流时。运行时库的提交到磁盘功能允许您确保将关键数据直接写入磁盘,而不是写入操作系统缓冲区。
正如其他人在评论中所说,您可能最好使用命名管道来实现您的目标,因为您只处理一个已知文件。
调用_flushall
(http://msdn.microsoft.com/en-us/library/s9xk9ehd.aspx ( 来强制提交到磁盘
或参阅这篇文章(http://support.microsoft.com/kb/148505(,了解如何强制提交到磁盘。您需要与commode.obj
链接以强制fflush
自动提交到磁盘。
另一种方法是每次fclose
文件,并在追加模式下重新打开文件,如果您每 2 秒只这样做一次(开销很小(。
看这里: https://jeffpar.github.io/kbarchive/kb/066/Q66052/
对我们来说,与commode.obj链接不起作用。
但是,这种方法确实:
当我们使用 fopen 打开文件时,我们包含了"c"模式选项作为最后一个选项:
fopen( path, "wc") // w - write mode, c - allow immediate commit to disk
然后,当您要强制刷新到磁盘时,请调用
_flushall()
我们在打电话之前打了这个电话
fclose()
我们遇到了您描述的确切问题,这种方法解决了它。
从上面的网站:
"Microsoft C/C++ 版本 7.0 为 fopen(( 引入了"c"模式选项功能。当应用程序打开文件并指定"c"模式时,运行时库将文件缓冲区的内容写入磁盘时应用程序调用 fflush(( 或 _flushall(( 函数。">
- 编译多个C++文件.调用二进制文件以运行代码
- 无法从 SO 文件调用 SO 文件的函数 - C++生成文件
- 如何从另一个文件调用类构造函数?
- 调用函数一次用于动态链接库,一次从可执行文件调用函数
- 当我从头文件和实现文件调用我的函数到我的主文件时,我没有得到任何输出
- 从 Android 中的 C 文件调用C++函数
- 从外部文件C++调用函数
- 如何从多个 cpp 文件调用函数
- 从用户定义的头文件调用函数时出现未定义的引用错误,其实现位于.cpp文件中
- cmake:生成批处理文件调用cl.exe
- 在文件中生成随机数,然后从文件调用它们,然后将它们打印出来
- main.cpp从 .h 文件调用公共虚拟方法
- 如何从 python (py) 文件调用 C++ 函数
- 如何从 cpp 文件调用 setRequestOrientation()
- 调试Visual Studio中可执行文件调用的C 文件
- 可以使用不同的头文件调用相同的函数吗?
- 从 Android 中的原生 c++ 文件调用本机 opencv
- 使用对象文件调用Winapi功能
- 从头文件调用字符串getter函数
- 方法从头文件调用