Question

Il y a beaucoup de programmes, Visual Studio par exemple, qui peut détecter lorsqu'un programme extérieur modifie un fichier, puis recharger le fichier si l'utilisateur veut Choisit. Y at-il un moyen relativement facile de faire ce genre de chose en C ++ (ne doit pas nécessairement être plate-forme)?

Était-ce utile?

La solution

Il y a plusieurs façons de le faire en fonction de la plate-forme. Je choisirais parmi les choix suivants:

Plate-forme Cross

Qt de Trolltech a un objet appelé QFileSystemWatcher qui vous permet de surveiller les fichiers et répertoires. Je suis sûr qu'il ya d'autres cadres multiplateformes qui vous donnent ce genre de capacité aussi, mais celui-ci fonctionne assez bien dans mon expérience.

(Windows Win32)

Il y a un api Win32 appelé FindFirstChangeNotification qui fait le travail. Il y a un bel article qui une petite classe wrapper pour le api appelé Comment obtenir une notification si le changement se produit dans un répertoire spécifié qui vous initieront.

(Windows .NET Framework)

Si vous êtes ok en C ++ / CLI avec le .NET Framework, puis System.IO.FileSystemWatcher est votre classe de choix. Microsoft a un bel article sur comment surveiller les changements du système de fichiers en utilisant cette classe.

OS X

API de FSEvents est nouvelle pour OS X 10.5 et très complet.

Linux

Utilisez inotify comme Alex mentionné dans sa réponse.

Autres conseils

Si vous une approche sur Linux qui peut être moins d'une charge de machine que « polling » (contrôle périodique) est inotify, voir pas besoin d'être indépendant de la plateforme, http://msdn.microsoft.com/ fr-fr / bibliothèque / aa365261 (VS.85) .aspx .

SimpleFileWatcher peut-être ce que vous recherchez. Mais bien sûr, il est une dépendance externe -. Peut-être ce n'est pas option pour vous

Bien sûr, tout comme le fait VC ++. Vous obtenez la dernière fois modifié lorsque vous ouvrez le fichier, et vous vérifiez régulièrement pendant que vous avez le fichier ouvert. Si last_mod_time> saved_mod_time, il est arrivé.

Un exemple de travail pour 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 );
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top