83

Visual Studioなど、外部プログラムがファイルを変更したことを検出し、ユーザーが選択した場合にファイルをリロードできるプログラムはたくさんあります。C ++でこの種のことを行う比較的簡単な方法はありますか(必ずしもプラットフォームに依存する必要はありません)?

4

6 に答える 6

122

これを行うには、プラットフォームに応じていくつかの方法があります。次の選択肢から選択します。

クロスプラットフォーム

Trolltech の Qt には、ファイルとディレクトリを監視できるQFileSystemWatcherというオブジェクトがあります。この種の機能を提供するクロスプラットフォーム フレームワークは他にもあると思いますが、私の経験では、これはかなりうまく機能します。

Windows (Win32)

仕事をするFindFirstChangeNotificationと呼ばれるWin32 APIがあります。指定されたディレクトリで変更が発生した場合に通知を取得する方法と呼ばれるAPIの小さなラッパークラスが開始する素晴らしい記事があります。

Windows (.NET フレームワーク)

.NET Framework で C++/CLI を使用しても問題ない場合は、 System.IO.FileSystemWatcherをクラスとして選択してください。Microsoft は、このクラスを使用してファイル システムの変更を監視する方法に関する優れた記事を公開 しています。

OS X

FSEvents API は OS X 10.5 の新機能であり、非常にフル機能を備えています。

Linux

アレックスが回答で述べたように、inotifyを使用します。

于 2009-05-31T03:10:24.390 に答える
22

プラットフォームに依存する必要がない場合は、「ポーリング」(定期的にチェック)よりもマシンの負荷が少ないLinuxでのアプローチはinotifyhttp://en.wikipedia.org/wiki/Inotifyおよびたとえば、そこからの多くのリンク。Windowsについては、 http://msdn.microsoft.com/en-us/library/aa365261( VS.85 ).aspxを参照してください。

于 2009-05-31T02:16:48.570 に答える
13

SimpleFileWatcherが探しているものかもしれません。しかしもちろん、それは外部依存関係です - おそらくそれはあなたにとって選択肢ではありません.

于 2015-04-07T11:05:38.760 に答える
5

もちろん、VC++と同じように。ファイルを開いたときに最終変更時刻を取得し、ファイルを開いている間、定期的にチェックします。last_mod_time> saved_mod_timeの場合、それが発生しました。

于 2009-05-31T02:13:57.780 に答える
5

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 );
}
于 2015-03-04T10:15:23.793 に答える