lenguaje - ¿Cómo hago que mi programa esté atento a la modificación de archivos en C++?
lectura y escritura de archivos en c++ (5)
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ó.
Hay muchos programas, por ejemplo Visual Studio, que pueden detectar cuándo un programa 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)
Sí, algunas personas usan C ++ / CLI con .NET Framework. 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.
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<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 );
}
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.
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 inotify y los muchos enlaces de este, por ejemplo. Para Windows, consulte http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx .