首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

VC/C++ 實現開啟中的 TXT 檔案即時刷新顯示:ReadDirectoryChangesW 監控檔案變更

     編輯:程式設計綜合問答

需求

記事本/編輯器開啟 TXT 檔案時,外部程式寫入新資料,編輯器能自動偵測並重新載入顯示(如 Notepad++ 行為)。

核心 API:ReadDirectoryChangesW

Windows 提供目錄/檔案變更通知機制,可非同步監控特定檔案的 `FILE_NOTIFY_CHANGE_LAST_WRITE` 事件。

實作步驟

  1. 建立目錄控制代碼:`CreateFile(目錄路徑, FILE_LIST_DIRECTORY, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL)`
  2. 啟動非同步監控:`ReadDirectoryChangesW(hDir, buffer, sizeof(buffer), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, &bytesReturned, &overlapped, NULL)`
  3. 完成埠/事件迴圈處理通知:收到 `FILE_ACTION_MODIFIED` 且檔名匹配 → 發送自訂訊息 `WM_FILE_CHANGED` 給主視窗。
  4. 主視窗處理:收到訊息 → `CStdioFile` 重新讀取整檔或增量 → `SetWindowText` / 追加內容 → 捲動至底。

關鍵程式碼片段


// 監控執行緒
DWORD WINAPI MonitorThread(LPVOID lpParam) {
    HANDLE hDir = CreateFile(dirPath, FILE_LIST_DIRECTORY, 
        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL,
        OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL);
    OVERLAPPED ol = {0}; ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    BYTE buffer[4096];
    while (running) {
        DWORD bytes;
        if (ReadDirectoryChangesW(hDir, buffer, sizeof(buffer), FALSE,
            FILE_NOTIFY_CHANGE_LAST_WRITE, &bytes, &ol, NULL)) {
            if (WaitForSingleObject(ol.hEvent, INFINITE) == WAIT_OBJECT_0) {
                FILE_NOTIFY_INFORMATION* fni = (FILE_NOTIFY_INFORMATION*)buffer;
                do {
                    if (fni->Action == FILE_ACTION_MODIFIED) {
                        CString changedFile(fni->FileName, fni->FileNameLength/2);
                        if (changedFile.CompareNoCase(targetFileName) == 0) {
                            ::PostMessage(hMainWnd, WM_FILE_CHANGED, 0, 0);
                        }
                    }
                    fni = (fni->NextEntryOffset) ? (FILE_NOTIFY_INFORMATION*)((BYTE*)fni + fni->NextEntryOffset) : NULL;
                } while (fni);
                ResetEvent(ol.hEvent);
            }
        }
    }
    CloseHandle(hDir);
    return 0;
}

替代方案(較簡單但有輪詢延遲)

  • FindFirstChangeNotification:較簡單 API,但只能通知「目錄有變更」,無法知曉具體檔案,需自行比對時間戳。
  • 定時器輪詢 `GetFileTime`:每 500ms~1s 比對 `LastWriteTime`,改變則重讀。適合輕量工具,CPU 佔用極低。

Notepad++ 參考

Notepad++ 正是使用 `ReadDirectoryChangesW` 非同步監控,發現外部修改後彈出「檔案已在別處修改,是否重新載入?」對話框。

總結

專業級即時刷新請用 **`ReadDirectoryChangesW` + 非同步 I/O + 完成埠**;輕量工具可用 **定時器輪詢時間戳**。核心在於「監控 → 通知 → 重讀 → 刷新 UI」四步閉環。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved