Pergunta

Há uma série de programas, Visual Studio por exemplo, que pode detectar quando um fora modifica programa de um arquivo e, em seguida, recarregar o arquivo se o usuário deseja escolher. Existe uma maneira relativamente fácil de fazer esse tipo de coisa em C ++ (não necessariamente tem que ser independente de plataforma)?

Foi útil?

Solução

Existem várias maneiras de fazer isso, dependendo da plataforma. Eu iria escolher uma das seguintes opções:

Cross Platform

O Qt da Trolltech tem um objeto chamado QFileSystemWatcher que lhe permite monitorar arquivos e diretórios. Eu tenho certeza que existem outros quadros de plataforma cruzada que lhe dão esse tipo de capacidade também, mas este funciona muito bem na minha experiência.

Windows (Win32)

Há uma API Win32 chamado FindFirstChangeNotification que faz o trabalho. Há um artigo agradável que uma pequena classe wrapper para a API chamada Como receber uma notificação se a mudança ocorre em um diretório especificado que irá ajudar a começar.

Windows (.NET Framework)

Se você estiver ok usando C ++ / CLI com o .NET Framework, em seguida, System.IO.FileSystemWatcher é a sua classe de escolha. Microsoft tem um artigo agradável em como monitorar mudanças do sistema de arquivos usando esta classe.

OS X

O FSEvents API é novo para OS X 10.5 e muito completo.

Linux

Use inotify como Alex mencionado na sua resposta.

Outras dicas

Se você não precisa ser independente de plataforma, uma abordagem sobre Linux que pode ser menos de uma carga da máquina de "polling" (verificar periodicamente) é inotify, consulte http://en.wikipedia.org/wiki/Inotify e as muitas ligações a partir dele, por exemplo. Para o Windows, consulte http://msdn.microsoft.com/ en-us / library / aa365261 (VS.85) .aspx .

SimpleFileWatcher pode ser o que você está procurando. Mas é claro que é uma dependência externa -. Talvez isso não é opção para você

Claro, assim como VC ++ faz. Você começa a última vez modificada quando você abre o arquivo, e você verificá-lo periodicamente enquanto você tem o arquivo aberto. Se last_mod_time> saved_mod_time, aconteceu.

Um exemplo de trabalho 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 );
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top