FileSystemWatcher.h
#pragma once
#ifndef __FILESYSTEMWATCHER_HPP__
#define __FILESYSTEMWATCHER_HPP__
#if(_WIN32_WINNT < 0x0400)
#define _WIN32_WINNT 0x0400
#endif
#include <windows.h>
class FileSystemWatcher
{
public:
enum Filter
{
FILTER_FILE_NAME = 0x00000001, // add/remove/rename
FILTER_DIR_NAME = 0x00000002, // add/remove/rename
FILTER_ATTR_NAME = 0x00000004,
FILTER_SIZE_NAME = 0x00000008,
FILTER_LAST_WRITE_NAME = 0x00000010, // timestamp
FILTER_LAST_ACCESS_NAME = 0x00000020, // timestamp
FILTER_CREATION_NAME = 0x00000040, // timestamp
FILTER_SECURITY_NAME = 0x00000100
};
enum ACTION
{
ACTION_ERRSTOP = -1,
ACTION_ADDED = 0x00000001,
ACTION_REMOVED = 0x00000002,
ACTION_MODIFIED = 0x00000003,
ACTION_RENAMED_OLD = 0x00000004,
ACTION_RENAMED_NEW = 0x00000005
};
typedef void(__stdcall* LPDEALFUNCTION)(ACTION act, LPCWSTR filename, LPVOID lParam);
FileSystemWatcher();
~FileSystemWatcher();
// LPCTSTR dir: dont end-with "\\"
bool Run(LPCTSTR dir, bool bWatchSubtree, DWORD dwNotifyFilter, LPDEALFUNCTION dealfun, LPVOID lParam);
void Close(DWORD dwMilliseconds = INFINITE);
private: // no-impl
FileSystemWatcher(const FileSystemWatcher&);
FileSystemWatcher operator=(const FileSystemWatcher);
private:
HANDLE m_hDir;
DWORD m_dwNotifyFilter;
bool m_bWatchSubtree;
HANDLE m_hThread;
volatile bool m_bRequestStop;
LPDEALFUNCTION m_DealFun;
LPVOID m_DealFunParam;
static DWORD WINAPI Routine(LPVOID lParam);
};
#endif // __FILESYSTEMWATCHER_HPP__
FileSystemWatcher.cpp
#include "FileSystemWatcher.h"
#include <cassert>
FileSystemWatcher::FileSystemWatcher() : m_hDir(INVALID_HANDLE_VALUE), m_hThread(NULL)
{
assert(FILTER_FILE_NAME == FILE_NOTIFY_CHANGE_FILE_NAME);
assert(FILTER_DIR_NAME == FILE_NOTIFY_CHANGE_DIR_NAME);
assert(FILTER_ATTR_NAME == FILE_NOTIFY_CHANGE_ATTRIBUTES);
assert(FILTER_SIZE_NAME == FILE_NOTIFY_CHANGE_SIZE);
assert(FILTER_LAST_WRITE_NAME == FILE_NOTIFY_CHANGE_LAST_WRITE);
assert(FILTER_LAST_ACCESS_NAME == FILE_NOTIFY_CHANGE_LAST_ACCESS);
assert(FILTER_CREATION_NAME == FILE_NOTIFY_CHANGE_CREATION);
assert(FILTER_SECURITY_NAME == FILE_NOTIFY_CHANGE_SECURITY);
assert(ACTION_ADDED == FILE_ACTION_ADDED);
assert(ACTION_REMOVED == FILE_ACTION_REMOVED);
assert(ACTION_MODIFIED == FILE_ACTION_MODIFIED);
assert(ACTION_RENAMED_OLD == FILE_ACTION_RENAMED_OLD_NAME);
assert(ACTION_RENAMED_NEW == FILE_ACTION_RENAMED_NEW_NAME);
}
FileSystemWatcher::~FileSystemWatcher()
{
Close();
}
bool FileSystemWatcher::Run(LPCTSTR dir, bool bWatchSubtree, DWORD dwNotifyFilter, LPDEALFUNCTION dealfun, LPVOID lParam)
{
Close();
m_hDir = CreateFile(//dir目录不能以'\'结尾,否则监测不到dir目录被删除,不以\结尾,可以检测到(仅限于空目录时)
dir,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL
);
if (INVALID_HANDLE_VALUE == m_hDir) return false;
m_bWatchSubtree = bWatchSubtree;
m_dwNotifyFilter = dwNotifyFilter;
m_DealFun = dealfun;
m_DealFunParam = lParam;
m_bRequestStop = false;
DWORD ThreadId;
m_hThread = CreateThread(NULL, 0, Routine, this, 0, &ThreadId);
if (NULL == m_hThread)
{
CloseHandle(m_hDir);
m_hDir = INVALID_HANDLE_VALUE;
}
return NULL != m_hThread;
}
void FileSystemWatcher::Close(DWORD dwMilliseconds)
{
if (NULL != m_hThread)
{
m_bRequestStop = true;
if (WAIT_TIMEOUT == WaitForSingleObject(m_hThread, dwMilliseconds))
TerminateThread(m_hThread, 0);
CloseHandle(m_hThread);
m_hThread = NULL;
}
if (INVALID_HANDLE_VALUE != m_hDir)
{
CloseHandle(m_hDir);
m_hDir = INVALID_HANDLE_VALUE;
}
}
DWORD WINAPI FileSystemWatcher::Routine(LPVOID lParam)
{
FileSystemWatcher& obj = *(FileSystemWatcher*)lParam;
BYTE buf[2 * (sizeof(FILE_NOTIFY_INFORMATION) + 2 * MAX_PATH) + 2];
FILE_NOTIFY_INFORMATION* pNotify = (FILE_NOTIFY_INFORMATION*)buf;
DWORD BytesReturned;
while (!obj.m_bRequestStop)
{
if (ReadDirectoryChangesW(obj.m_hDir,
pNotify,
sizeof(buf) - 2,
obj.m_bWatchSubtree,
obj.m_dwNotifyFilter,
&BytesReturned,
NULL,
NULL)) // 无限等待,应当使用异步方式
{
for (FILE_NOTIFY_INFORMATION* p = pNotify; p; )
{
WCHAR c = p->FileName[p->FileNameLength / 2];
p->FileName[p->FileNameLength / 2] = L'\0';
obj.m_DealFun((ACTION)p->Action, p->FileName, obj.m_DealFunParam);
p->FileName[p->FileNameLength / 2] = c;
if (p->NextEntryOffset)
p = (PFILE_NOTIFY_INFORMATION)((BYTE*)p + p->NextEntryOffset);
else
p = 0;
}
}
else
{
obj.m_DealFun((ACTION)ACTION_ERRSTOP, 0, obj.m_DealFunParam);
break;
}
}
return 0;
}
ConsoleApplication2.cpp
//#include "stdafx.h"
#include "yolo.h"
#include <iostream>
#include<opencv2//opencv.hpp>
#include<math.h>
#include <ctime>
#include <iomanip>
#include <filesystem>
#include "FileSystemWatcher.h"
#include <stdio.h>
#include <locale.h>
#include <assert.h>
#include <tchar.h>
#include <conio.h>
#include <fstream>
using namespace std;
using namespace cv;
using namespace dnn;
namespace fs = std::filesystem;
//该函数LPCWSTR转string类型
std::string LPCWSTRToString(LPCWSTR lpcwstr) {
int len = WideCharToMultiByte(CP_UTF8, 0, lpcwstr, -1, NULL, 0, NULL, NULL);
std::string str(len, '\0');
WideCharToMultiByte(CP_UTF8, 0, lpcwstr, -1, &str[0], len, NULL, NULL);
return str;
}
void __stdcall MyDeal(FileSystemWatcher::ACTION act, LPCWSTR filename, LPVOID lParam)
{
static FileSystemWatcher::ACTION pre = FileSystemWatcher::ACTION_ERRSTOP;
switch (act)
{
case FileSystemWatcher::ACTION_ADDED: {
wprintf_s(L"Added - %s\n", filename);
std::string str = LPCWSTRToString(filename); //转换为string类型
std::cout << str;
break;
}
case FileSystemWatcher::ACTION_REMOVED:
wprintf_s(L"Removed - %s\n", filename);
break;
case FileSystemWatcher::ACTION_MODIFIED:
wprintf_s(L"Modified - %s\n", filename);
break;
case FileSystemWatcher::ACTION_RENAMED_OLD:
wprintf_s(L"Rename(O) - %s\n", filename);
break;
case FileSystemWatcher::ACTION_RENAMED_NEW:
assert(pre == FileSystemWatcher::ACTION_RENAMED_OLD);
wprintf_s(L"Rename(N) - %s\n", filename);
break;
case FileSystemWatcher::ACTION_ERRSTOP:
default:
wprintf_s(L"---ERROR---%s\n", filename);
break;
}
pre = act;
}
int main()
{
LPCTSTR sDir = TEXT("D:/sourceImgs");
DWORD dwNotifyFilter = FileSystemWatcher::FILTER_FILE_NAME | FileSystemWatcher::FILTER_DIR_NAME;
FileSystemWatcher fsw;
bool r = fsw.Run(sDir, true, dwNotifyFilter, &MyDeal, 0);
if (!r) return -1;
_tsetlocale(LC_CTYPE, TEXT("chs"));
_tprintf_s(TEXT("Watch%s\n"), sDir);
_tprintf_s(TEXT("Press <q> to quit.\n"));
while (_getch() != 'q');
fsw.Close(1000);
return 0;
}
C++的监听文件是在找不到,也是偶然间看到的,我在这里加了LPCWSTR类型转换为string类型