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类型

08-18 13:22