如何让我的程序监视C ++中的文件修改?

有很多程序,例如Visual Studio,可以检测外部程序何时修改文件,然后在用户select时重新加载文件。 有没有一种相对简单的方法来做这种事情在C + +(不一定是平台独立)?

根据平台,有几种方法可以做到这一点。 我会select以下select:

跨平台

奇趣科技的Qt有一个名为QFileSystemWatcher的对象,它允许您监视文件和目录。 我相信还有其他的跨平台框架可以为你提供这种function,但是这个function在我的经验中运行的很好。

Windows(Win32)

有一个叫做FindFirstChangeNotification的Win32 api来完成这个工作。 有一个很好的文章,一个小的包装类的API调用如何获得通知,如果更改发生在指定的目录 ,这将启动。

Windows(.NET Framework)

是的,有些人在.NET框架中使用C ++ / CLI。 System.IO.FileSystemWatcher是你的select。 Microsoft有一篇关于如何使用这个类来监视文件系统更改的不错文章。

OS X

FSEvents API是OS X 10.5的新function,function非常全面。

Linux的

像Alex在他的回答中提到的那样使用inotify 。

如果您不需要独立于平台,那么Linux上的方法可能比“轮询”(定期检查)的机器负载要less,请参阅http://en.wikipedia.org/wiki/Inotify和从它的很多链接,例如。; 对于Windows,请参阅http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx 。

当然,就像VC ++一样。 打开文件时会得到最后一次修改的时间,并在打开文件时定期检查它。 如果last_mod_time> saved_mod_time,则发生。

SimpleFileWatcher可能是你正在寻找的。 但当然这是一个外部的依赖 – 也许这对你来说是没有select的。

一个WinCE的工作例子

 void FileInfoHelper::WatchFileChanges( TCHAR *ptcFileBaseDir, TCHAR *ptcFileName ){ static int iCount = 0; DWORD dwWaitStatus; HANDLE dwChangeHandles; if( ! ptcFileBaseDir || ! ptcFileName ) return; wstring wszFileNameToWatch = ptcFileName; dwChangeHandles = FindFirstChangeNotification( ptcFileBaseDir, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY | FILE_NOTIFY_CHANGE_CEGETINFO ); if (dwChangeHandles == INVALID_HANDLE_VALUE) { printf("\n ERROR: FindFirstChangeNotification function failed [%d].\n", GetLastError()); return; } while (TRUE) { // Wait for notification. printf("\n\n[%d] Waiting for notification...\n", iCount); iCount++; dwWaitStatus = WaitForSingleObject(dwChangeHandles, INFINITE); switch (dwWaitStatus) { case WAIT_OBJECT_0: printf( "Change detected\n" ); DWORD iBytesReturned, iBytesAvaible; if( CeGetFileNotificationInfo( dwChangeHandles, 0, NULL, 0, &iBytesReturned, &iBytesAvaible) != 0 ) { std::vector< BYTE > vecBuffer( iBytesAvaible ); if( CeGetFileNotificationInfo( dwChangeHandles, 0, &vecBuffer.front(), vecBuffer.size(), &iBytesReturned, &iBytesAvaible) != 0 ) { BYTE* p_bCurrent = &vecBuffer.front(); PFILE_NOTIFY_INFORMATION info = NULL; do { info = reinterpret_cast<PFILE_NOTIFY_INFORMATION>( p_bCurrent ); p_bCurrent += info->NextEntryOffset; if( wszFileNameToWatch.compare( info->FileName ) == 0 ) { wcout << "\n\t[" << info->FileName << "]: 0x" << ::hex << info->Action; switch(info->Action) { case FILE_ACTION_ADDED: break; case FILE_ACTION_MODIFIED: break; case FILE_ACTION_REMOVED: break; case FILE_ACTION_RENAMED_NEW_NAME: break; case FILE_ACTION_RENAMED_OLD_NAME: break; } } }while (info->NextEntryOffset != 0); } } if ( FindNextChangeNotification( dwChangeHandles ) == FALSE ) { printf("\n ERROR: FindNextChangeNotification function failed [%d].\n", GetLastError()); return; } break; case WAIT_TIMEOUT: printf("\nNo changes in the timeout period.\n"); break; default: printf("\n ERROR: Unhandled dwWaitStatus [%d].\n", GetLastError()); return; break; } } FindCloseChangeNotification( dwChangeHandles ); }