Domanda

Ci sono un sacco di programmi, Visual Studio, per esempio, in grado di rilevare quando un fuori programma modifica un file e quindi ricaricare il file se l'utente vuole sceglie. C'è un modo relativamente facile da fare questo genere di cose in C ++ (non necessariamente deve essere indipendente dalla piattaforma)?

È stato utile?

Soluzione

Ci sono diversi modi per fare questo a seconda della piattaforma. Vorrei scegliere fra le seguenti opzioni:

Cross Platform

Qt di Trolltech ha un oggetto chiamato QFileSystemWatcher che consente di monitorare i file e le directory. Sono sicuro che ci sono altri framework multipiattaforma che ti danno questo tipo di capacità di troppo, ma questo funziona abbastanza bene nella mia esperienza.

di Windows (Win32)

C'è un'API Win32 chiamata FindFirstChangeNotification , che fa il lavoro. C'è un bel articolo che una piccola classe wrapper per le API chiamata Come ricevere una notifica se il cambiamento si verifica in un directory specificata, che vi consentiranno di iniziare.

di Windows (.NET Framework)

Se vi sono ok con C ++ / CLI con .NET Framework poi System.IO.FileSystemWatcher è la classe di scelta. Microsoft ha un bell'articolo su come monitorare i cambiamenti del file system utilizzando questa classe.

OS X

Il FSEvents API è nuovo per OS X 10.5 e molto full-optional.

Linux

inotify come Alex menzionato nella sua risposta.

Altri suggerimenti

Se non c'è bisogno di essere indipendente dalla piattaforma, un approccio su Linux che può essere meno di un carico macchina rispetto "polling" (verifica periodica) è inotify, vedere http://en.wikipedia.org/wiki/Inotify ei numerosi collegamenti da essa, per esempio. Per Windows, vedere http://msdn.microsoft.com/ it-it / library / aa365261 (VS.85) aspx .

SimpleFileWatcher potrebbe essere quello che stai cercando. Ma naturalmente si tratta di una dipendenza esterna -. Forse questo non è un opzione per voi

Certo, proprio come VC ++ fa. È possibile ottenere la data dell'ultima modifica quando si apre il file, e controllare periodicamente mentre si ha il file aperto. Se last_mod_time> saved_mod_time, è successo.

Un esempio di lavoro per 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 );
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top