C++ 使用ReadDirectoryChangesW监测文件夹

直接上代码:

FileSystemWatcher.h

#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;
}

 

main函数

#include "FileSystemWatcher.h"
#include <stdio.h>
#include <locale.h>
#include <assert.h>
#include <tchar.h>
#include <conio.h>

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 );
		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:\\监测文件夹");
	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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值