来源:http://blog.sina.com.cn/s/blog_a6fb6cc901017urz.html
文件监控之FileSystemWatcher(C++详解)
些天在研究一些文件监控方面的知识,把自己积累的一些小知识拿出来和大家分享一下,为了能让更多的人能够更容易看明白,我特意加了一些注释,不算很详细,但是理解起来应该更轻松一点,希望各位大虾多多指正。。。技术在于交流嘛!如果希望能多了解一些文件监控方面的知识,请参考我的另一篇文章——文件监控之ReadDirectoryChangesW(C++详解)。
1 #using 2 #include 3 #include 4 #include 5 6 using namespace System; 7 using namespace System::IO; 8 9 ref class FSEventHandler 10 { 11 private: 12 static int count = 0; 13 14 void OnChanged (Object^ source, FileSystemEventArgs^ e) 15 { 16 //当文件改变、创建、或者删除时执行的动作(count用于批量监控,可以测试由于粘贴大批量文件而是否引发监测漏洞问题) 17 Console::WriteLine("{0} File:{1} ChangeType:{2}", 18 ++count, e->FullPath, e->ChangeType, e->Name); 19 } 20 21 void OnRenamed(Object^ source, RenamedEventArgs^ e) 22 { 23 //定义文件重命名时执行的动作 24 Console::WriteLine("{0} File:{1} renamed to:{2}", 25 ++count, e->OldFullPath, e->FullPath); 26 } 27 28 public: 29 int static run() 30 { 31 //创建一个FileSystemWatcher并设置它的属性. 32 FileSystemWatcher^ fsWatcher = gcnew FileSystemWatcher( ); 33 34 fsWatcher->Path = "E:\wang"; 35 36 37 //设置缓冲区大小1M,根据需求设置 38 fsWatcher->InternalBufferSize = 1048576; 39 40 //监听文件、目录、文件大小的改变 41 fsWatcher->NotifyFilter = static_cast 42 (NotifyFilters::FileName | 43 NotifyFilters::DirectoryName | 44 NotifyFilters::Size); 45 46 //监听子目录 47 fsWatcher->IncludeSubdirectories = true; 48 49 //添加事件处理程序 50 FSEventHandler^ handler = gcnew FSEventHandler(); 51 52 fsWatcher->Changed += gcnew FileSystemEventHandler( 53 handler, &FSEventHandler::OnChanged); 54 55 fsWatcher->Created += gcnew FileSystemEventHandler( 56 handler, &FSEventHandler::OnChanged); 57 58 fsWatcher->Deleted += gcnew FileSystemEventHandler( 59 handler, &FSEventHandler::OnChanged); 60 61 fsWatcher->Renamed += gcnew RenamedEventHandler( 62 handler, &FSEventHandler::OnRenamed); 63 64 //开始监听 65 fsWatcher->EnableRaisingEvents = true; 66 67 Console::WriteLine("Press Enter to quit the sample."); 68 69 Console::ReadLine(); 70 return 0; 71 } 72 }; 73 74 75 int main() 76 77 { 78 FSEventHandler::run(); 79 }
注意事项(步骤):
1、创建FileSystemWatcher,并设置它的属性(例如:设置监控的目录就需设置Path属性,设置缓冲区大小就需设置InternalBufferSize属性)。
2、根据需求适当设置缓冲区大小,否则有可能会因大批量文件造成监控遗漏问题(例:同时复制或者删除1000个文件,可能只检测到500、600个)。InternalBufferSize属性用于获取或设置内部缓冲区的大小,默认值为4096(4KB)。内部缓冲区用来存储监视到的更改信息。如果短时间内更改过多,则缓冲区会发生溢出,导致某些监视到的更改数据丢失。但是增加缓冲区大小,会使系统的运行开销增大,因此,适当设置缓冲区大小,若要避免缓冲区溢出,则使用NotifyFilter和IncludeSubdirectories属性筛选掉不想要的更改通知,如果内部缓冲区溢出,组件将引发Error事件。
3、指定在文件、文件夹中监听的更改(例:NotifyFilters::FileName | NotifyFilters::DirectoryName | NotifyFilters::Size监听文件、目录、文件大小的改变)
4、监听子目录,设置fsWatcher->IncludeSubdirectories = true;
5、添加事件处理程序,主要包括:Changed、Create、Delete、Ranamed。
以下为我将InternalBufferSize的大小设置为1M的时候监听同时删除12000个文本文档的截图,
来源:http://blog.sina.com.cn/s/blog_a6fb6cc901017us1.html
文件监控之ReadDirectoryChangesW(C++详解)
上篇文章跟大家分享了关于FileSystemWatcher来实现对文件夹的监控,这篇文章主要介绍文件监控的另一种实现方式,利用ReadDirectoryChangesW来实现文件的监控,希望对大家有帮助!
1 #include 2 #include 3 #include 4 #include 5 using namespace std; 6 #define MAX_PATH 1024 7 8 9 void fileWatcher(); 10 11 int main() 12 { 13 fileWatcher(); 14 return 0; 15 } 16 17 void fileWatcher() 18 { 19 DWORD cbBytes; 20 char file_name[MAX_PATH]; //设置文件名 21 char file_name2[MAX_PATH]; //设置文件重命名后的名字 22 char notify[1024]; 23 int count = 0; //文件数量。可能同时拷贝、删除多个文件,可以进行更友好的提示。 24 25 TCHAR *dir = _T("E:\liang"); 26 27 HANDLE dirHandle = CreateFile(dir,GENERIC_READ | GENERIC_WRITE | FILE_LIST_DIRECTORY, 28 FILE_SHARE_READ | FILE_SHARE_WRITE, 29 NULL, 30 OPEN_EXISTING, 31 FILE_FLAG_BACKUP_SEMANTICS, 32 NULL); 33 34 if(dirHandle == INVALID_HANDLE_VALUE) //若网络重定向或目标文件系统不支持该操作,函数失败,同时调用GetLastError()返回ERROR_INVALID_FUNCTION 35 { 36 cout<<"error"+GetLastError()<<endl; 37 } 38 39 memset(notify,0,strlen(notify)); 40 41 FILE_NOTIFY_INFORMATION *pnotify = (FILE_NOTIFY_INFORMATION*)notify; 42 cout<<"start...."<<endl; 43 44 while(true) 45 { 46 if(ReadDirectoryChangesW(dirHandle,¬ify,1024,true, 47 FILE_NOTIFY_CHANGE_FILE_NAME | 48 FILE_NOTIFY_CHANGE_DIR_NAME 49 //| FILE_NOTIFY_CHANGE_CREATION 50 //| FILE_NOTIFY_CHANGE_LAST_WRITE 51 | FILE_NOTIFY_CHANGE_SIZE, 52 &cbBytes,NULL,NULL)) 53 { 54 //转换文件名为多字节字符串 55 if(pnotify->FileName) 56 { 57 memset(file_name,0,strlen(file_name)); 58 59 WideCharToMultiByte(CP_ACP,0,pnotify->FileName,pnotify->FileNameLength/2,file_name,99,NULL,NULL); 60 } 61 62 //获取重命名的文件名 63 if(pnotify->NextEntryOffset !=0 && (pnotify->FileNameLength > 0 && pnotify->FileNameLength < MAX_PATH)) 64 65 { 66 PFILE_NOTIFY_INFORMATION p = (PFILE_NOTIFY_INFORMATION)((char*)pnotify+pnotify->NextEntryOffset); 67 68 memset(file_name2,0,sizeof(file_name2) ); 69 70 WideCharToMultiByte(CP_ACP,0,p->FileName,p->FileNameLength/2,file_name2,99,NULL,NULL ); 71 } 72 73 //设置类型过滤器,监听文件创建、更改、删除、重命名等 74 switch(pnotify->Action) 75 { 76 case FILE_ACTION_ADDED: 77 count++; 78 cout<<count<<setw(5)<<"file add:"<<setw(5)<<file_name<<endl; 79 break; 80 case FILE_ACTION_MODIFIED: 81 cout<<"file modified:"<<setw(5)<<file_name<<endl; 82 break; 83 case FILE_ACTION_REMOVED: 84 count++; 85 cout<<count<<setw(5)<<"file removed:"<<setw(5)<<file_name<<endl; 86 break; 87 case FILE_ACTION_RENAMED_OLD_NAME: 88 cout<<"file renamed:"<<setw(5)<<file_name<<"->"<<file_name2<<endl; 89 break; 90 default: 91 cout<<"unknow command!"<<endl; 92 } 93 } 94 } 95 96 CloseHandle(dirHandle); 97 }
注意事项(步骤):
1、通过CreateFile获取要监控的目录句柄。
2、通过ReadDirectoryChangesW来监测到文件系统的变化,还能够返回详细的文件变动的信息,并且能够选择是使用同步方式检测还是异步方式监测。
3、通过Action设置类型过滤器,根据过滤器的设置,ReadDirectoryChangesW函数可以监控文件名改变、文件属性改变、文件大小改变、文件内容被改写、文件被删除等多种类型的变化。