简介:
使用FindFirstChangeNotificationW监听指定路径文件变化,入参为文件夹路径(不是文件名),WaitForSingleObject等待文件夹变化,读取内部所有文件及其修改时间,只刷新最新修改的。以下基于C++17版本
类似可以搜索watch4folder、Directory Monitor 2等工具使用
代码:
#include <iostream>
#include <windows.h>
#include <fstream>
#include <unordered_map>
#include <string>
// 记录文件的修改时间
std::unordered_map<std::wstring, FILETIME> lastModifiedTimes;
void watchFile(const std::wstring& directory) {
// 设置监视路径
HANDLE hChange = FindFirstChangeNotificationW(
directory.c_str(), // 监视目录路径
FALSE, // 不递归子目录
FILE_NOTIFY_CHANGE_LAST_WRITE // 监听文件修改(最后写入时间)
);
if (hChange == INVALID_HANDLE_VALUE) {
DWORD dwError = GetLastError();
std::cerr << "Failed to set up the change notification! Error code: " << dwError << std::endl;
return;
}
std::cout << "Watching directory for changes..." << std::endl;
while (true) {
// 等待文件夹变化
DWORD dwWaitStatus = WaitForSingleObject(hChange, INFINITE);
if (dwWaitStatus == WAIT_OBJECT_0) {
// 文件夹内某个文件发生了变化
std::wcout << L"Detected a file change in directory: " << directory << std::endl;
// 遍历目录中的所有文件
WIN32_FIND_DATA findFileData;
HANDLE hFind = FindFirstFile((directory + L"\\*").c_str(), &findFileData);
if (hFind == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to find files in the directory!" << std::endl;
return;
}
do {
if (wcscmp(findFileData.cFileName, L".") != 0 && wcscmp(findFileData.cFileName, L"..") != 0) {
std::wstring filePath = directory + L"\\" + findFileData.cFileName;
HANDLE hFile = CreateFile(filePath.c_str(), GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
FILETIME ftLastWriteTime;
if (GetFileTime(hFile, NULL, NULL, &ftLastWriteTime)) {
if (lastModifiedTimes.find(filePath) == lastModifiedTimes.end() ||
CompareFileTime(&ftLastWriteTime, &lastModifiedTimes[filePath]) != 0) {
lastModifiedTimes[filePath] = ftLastWriteTime; // 更新文件的修改时间
std::wcout << L"File " << filePath << L" has been modified!" << std::endl;
// 读取文件内容
std::wifstream file(filePath);
if (file.is_open()) {
std::wcout << L"File content:\n";
std::wcout << file.rdbuf() << std::endl;
} else {
std::cerr << "Failed to open the file!" << std::endl;
}
}
} else {
std::cerr << "Failed to get file time for: " << filePath << std::endl;
}
CloseHandle(hFile);
} else {
std::cerr << "Failed to open file: " << filePath << std::endl;
}
}
} while (FindNextFile(hFind, &findFileData) != 0);
FindClose(hFind);
// 重新设置通知,以便继续监听
if (!FindNextChangeNotification(hChange)) {
std::cerr << "Failed to reset change notification!" << std::endl;
return;
}
} else if (dwWaitStatus == WAIT_FAILED) {
std::cerr << "Error while waiting for changes!" << std::endl;
return;
}
}
FindCloseChangeNotification(hChange);
}
int main() {
std::wstring directoryPath = L"F:\\SteamLibrary\\steamapps\\common\\MonsterHunterRise\\reframework\\data";
watchFile(directoryPath); // 开始监听目录
return 0;
}