简体   繁体   English

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

[英]How do I make my program watch for file modification in C++?

There are a lot of programs, Visual Studio for instance, that can detect when an outside program modifies a file and then reload the file if the user wants chooses. 有很多程序,例如Visual Studio,可以检测外部程序何时修改文件,然后在用户愿意时重新加载文件。 Is there a relatively easy way to do this sort of thing in C++ (doesn't necessarily have to be platform independent)? 有没有相对简单的方法可以在C ++中完成这种事情(不一定必须独立于平台)?

There are several ways to do this depending on the platform. 取决于平台,有几种方法可以执行此操作。 I would choose from the following choices: 我将从以下选择中进行选择:

Cross Platform 跨平台

Trolltech's Qt has an object called QFileSystemWatcher which allows you to monitor files and directories. 奇趣的Qt有一个名为QFileSystemWatcher的对象,该对象使您可以监视文件和目录。 I'm sure there are other cross platform frameworks that give you this sort of capability too, but this one works fairly well in my experience. 我确信还有其他跨平台框架也可以为您提供这种功能,但是根据我的经验,这个功能相当不错。

Windows (Win32) Windows(Win32)

There is a Win32 api called FindFirstChangeNotification which does the job. 有一个名为FindFirstChangeNotification的Win32 API可以完成这项工作。 There is a nice article which a small wrapper class for the api called How to get a notification if change occurs in a specified directory which will get you started. 有一篇不错的文章,其中有一个小型的api包装类,名为“ 如何在指定目录中发生更改时获取通知”,这将使您入门。

Windows (.NET Framework) Windows(.NET Framework)

If you are ok using C++/CLI with the .NET Framework then System.IO.FileSystemWatcher is your class of choice. 如果可以将C ++ / CLI与.NET Framework一起使用,则可以选择System.IO.FileSystemWatcher Microsoft has a nice article on how to monitor file system changes using this class. Microsoft有一篇不错的文章, 介绍如何使用此类监视文件系统更改

OS X OS X

The FSEvents API is new for OS X 10.5 and very full-featured. FSEvents API是OS X 10.5的新增功能,并且功能非常全。

Linux 的Linux

Use inotify as Alex mentioned in his answer. 使用inotify,就像Alex在回答中提到的那样。

If you don't need to be platform-independent, an approach on Linux that may be less of a machine load than "polling" (checking periodically) is inotify , see http://en.wikipedia.org/wiki/Inotify and the many links from it for example. 如果您不需要独立于平台,则inotify可以在Linux上减轻机器负担,而不是“轮询”(定期检查),请参见http://en.wikipedia.org/wiki/Inotify和例如,它的许多链接。 For Windows, see http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx . 对于Windows,请参见http://msdn.microsoft.com/zh-cn/library/aa365261(VS.85).aspx

SimpleFileWatcher might be what you are looking for. 可能正在寻找SimpleFileWatcher But of course it is an external dependency - maybe that is no option for you. 但是,当然这是一个外部依赖关系-也许这对您来说不是选择。

A working exemple for WinCE 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 );
}

Sure, just like VC++ does. 当然,就像VC ++一样。 You get the last modified time when you open the file, and you periodically check it while you have the file open. 打开文件时,您会获得上次修改时间,并且在打开文件时会定期检查它。 If last_mod_time > saved_mod_time, it happened. 如果last_mod_time> saved_mod_time,则发生了。

Add an answer for libuv (though it's written in C), it has support for both Windows and Linux with system-specific APIs: 添加libuv的答案(尽管它是用C编写的),它通过系统特定的API支持Windows和Linux:

inotify on Linux, FSEvents on Darwin, kqueue on BSDs, ReadDirectoryChangesW on Windows, event ports on Solaris, unsupported on Cygwin 在Linux上是inotify,在Darwin上是FSEvents,在BSD上是kqueue,在Windows上是ReadDirectoryChangesW,在Solaris上是事件端口,Cygwin不支持

You may check the document here , beware that the document says that the notification related APIs are not very consistent. 您可以在此处查看文档,请注意该文档指出与通知相关的API不一致。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM