windows 文件监控 c++ 11及以上版本可用
在该版本上稍微改了一下https://blog.csdn.net/weixin_50964512/article/details/125002563
#include<iostream>
#include<string>
#include<Windows.h>
#include<list>
#include<locale>
using namespace std;
class WatchFolder {
HANDLE m_hFile; //进行监视的文件句柄
char* m_buf; //保存文件信息更改的缓存区
public:
struct FILE_INFO
{
std::wstring name;
DWORD action;
FILE_INFO(const wchar_t* fileName, DWORD act) {
name = fileName;
action = act;
}
};
//可监视的属性
enum {
NOTIFY_FILE_NAME = FILE_NOTIFY_CHANGE_FILE_NAME, //监视文件名更改
NOTIFY_DIR_NAME = FILE_NOTIFY_CHANGE_DIR_NAME, //监视目录名更改
NOTIFY_ATTRIBUTES = FILE_NOTIFY_CHANGE_ATTRIBUTES, //监视文件属性更改
NOTIFY_SIZE = FILE_NOTIFY_CHANGE_SIZE, //监视文件大小更改
NOTIFY_LAST_WRITE = FILE_NOTIFY_CHANGE_LAST_WRITE, //监视文件最后写入时间更改
NOTIFY_LAST_ACCESS = FILE_NOTIFY_CHANGE_LAST_ACCESS, //监视文件最后访问时间更改
NOTIFY_CREATION = FILE_NOTIFY_CHANGE_CREATION, //监视文件创建
NOTIFY_SECURITY = FILE_NOTIFY_CHANGE_SECURITY, //监视文件安全描述符更改
NOTIFY_ALL = NOTIFY_DIR_NAME|NOTIFY_FILE_NAME|NOTIFY_SIZE| NOTIFY_LAST_WRITE| NOTIFY_LAST_ACCESS| NOTIFY_CREATION| NOTIFY_ATTRIBUTES| NOTIFY_SECURITY //监视所有情况
};
//发生的行为
enum {
ACTION_ADD = FILE_ACTION_ADDED, //文件添加
ACTION_REMOVE = FILE_ACTION_REMOVED, //文件删除
ACTION_MODIFIED = FILE_ACTION_MODIFIED, //文件更改
ACTION_RENAME_OLD=FILE_ACTION_RENAMED_OLD_NAME, //文件重命名(旧名字)
ACTION_RENAME_NEW=FILE_ACTION_RENAMED_NEW_NAME //文件重命名(新名字)
};
public:
WatchFolder(int bufSize=4096) {
m_hFile = nullptr;
m_buf = new char[bufSize];
}
~WatchFolder()
{
Close();
delete[] m_buf;
}
/**
* @brief 初始化要进行监视的文件
* @param dir
* @return
*/
bool Init(const std::wstring& dir) {
if (m_hFile != nullptr) {
CloseHandle(m_hFile);
m_hFile = nullptr;
}
//打开文件
m_hFile = CreateFileW(dir.data(), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE| FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
return m_hFile != nullptr;
}
/**
* @brief 关闭打开的文件句柄
*/
void Close() {
if(m_hFile!=nullptr) CloseHandle(m_hFile);
}
/**
* @brief 开始监视文件夹
* @param fileInfo 返回发生改变的文件信息
* @param filter 要进行监视的文件行为,可使用WatchFolder::NOTIFY_*
* @param IsWatchSubTree 是否监视子目录
* @return 存在文件更改信息返回true,否则返回false
*/
bool BeginMonitor(std::list<FILE_INFO>& fileInfo, DWORD filter, bool IsWatchSubTree = false) {
fileInfo.clear(); //清空列表
DWORD lbyte; //得到返回的字节数
BOOL ret = ReadDirectoryChangesW(m_hFile, m_buf, 4096, IsWatchSubTree, filter, &lbyte, NULL, NULL); //阻塞监视
if (!ret ) return false; //失败
FILE_NOTIFY_INFORMATION* event;
DWORD offset = 0;
//进入循环,解析所有信息
do {
event= (FILE_NOTIFY_INFORMATION*)(m_buf+offset); //得到FILE_NOTIFY_INFORMATION结构体,进行解析= (FILE_NOTIFY_INFORMATION*)m_buf; //得到FILE_NOTIFY_INFORMATION结构体,进行解析
DWORD action=event->Action;
wchar_t* fileName = new wchar_t[event->FileNameLength] {};
memcpy(fileName, event->FileName, event->FileNameLength);
fileInfo.push_back({ fileName,action});
delete[] fileName;
offset += event->NextEntryOffset;
} while (event->NextEntryOffset!=0);
delete event;
memset(m_buf, 0, lbyte); //清空缓存区
return !fileInfo.empty();
}
};
int main() {
setlocale(LC_ALL, "");
WatchFolder fol;
bool ret = fol.Init(L"D:\\");
if (!ret) {
cout << "初始化失败";
return -1;
}
list<WatchFolder::FILE_INFO> res;
while (fol.BeginMonitor(res, WatchFolder::NOTIFY_ALL, true)) {
for (auto& i : res) {
switch (i.action)
{
case WatchFolder::ACTION_ADD:
wcout << i.name << L":\t文件被添加" << endl;
break;
case WatchFolder::ACTION_REMOVE:
wcout << i.name << L":\t文件被删除" << endl;
break;
case WatchFolder::ACTION_MODIFIED:
wcout << i.name << L":\t文件被更改" << endl;
break;
case WatchFolder::ACTION_RENAME_OLD:
wcout << i.name << L":\t文件重命名" << endl;
break;
case WatchFolder::ACTION_RENAME_NEW:
wcout << i.name << L":\t文件新名字" << endl;
break;
default:
break;
}
}
}
}