¿Cómo hago que mi progtwig esté atento a la modificación de archivos en C ++?

Hay muchos progtwigs, por ejemplo Visual Studio, que pueden detectar cuándo un progtwig externo modifica un archivo y luego volver a cargarlo si el usuario lo desea. ¿Hay alguna manera relativamente fácil de hacer este tipo de cosas en C ++ (no necesariamente tiene que ser independiente de la plataforma)?

Hay varias formas de hacer esto dependiendo de la plataforma. Yo elegiría entre las siguientes opciones:

Plataforma cruzada

Qt de Trolltech tiene un objeto llamado QFileSystemWatcher que le permite monitorear archivos y directorios. Estoy seguro de que hay otros frameworks multiplataforma que también le dan este tipo de capacidad, pero esta funciona bastante bien en mi experiencia.

Windows (Win32)

Hay una API de Win32 llamada FindFirstChangeNotification que hace el trabajo. Hay un buen artículo en el que una pequeña clase de contenedor para la API se llama Cómo recibir una notificación si se produce un cambio en un directorio específico que le permitirá comenzar.

Windows (.NET Framework)

Si está bien usando C ++ / CLI con .NET Framework entonces System.IO.FileSystemWatcher es su clase de elección. Microsoft tiene un buen artículo sobre cómo monitorear los cambios en el sistema de archivos usando esta clase.

OS X

La API de FSEvents es nueva para OS X 10.5 y tiene muchas funciones.

Linux

Usa inotify como Alex mencionó en su respuesta.

Si no necesita ser independiente de la plataforma, un enfoque en Linux que puede ser menos carga de una máquina que “sondeo” (verificando periódicamente) es inotify , vea http://en.wikipedia.org/wiki/Inotify y los muchos enlaces de este, por ejemplo. Para Windows, consulte http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx .

SimpleFileWatcher podría ser lo que estás buscando. Pero, por supuesto, es una dependencia externa; tal vez esa no sea una opción para ti.

Claro, al igual que VC ++. Obtiene la última vez que se modificó cuando abre el archivo, y lo verifica periódicamente mientras tiene el archivo abierto. Si last_mod_time> saved_mod_time, sucedió.

Un ejemplo de trabajo para 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( 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 ); }