Windows快速检索文件MFC实例
来源:互联网 发布:实物货源软件 编辑:程序博客网 时间:2024/05/06 14:45
在这段时间总共是做了两个快速检索的代码,一个是win32程序,在搜来的源代码的基础上稍作改动得来的,代码较为复杂。二个是用MFC写的,主要是根据网上这方面的资料和demo进行编写的代码。以下是MFC工程的具体实现方法。
设计思路
读取磁盘全部文件\文件夹名称作为数据,根据用户输入的关键字,在数据库中模糊匹配,符合条件的连同路径一起返回给用户,方便打开文件。
具体实现方法
1、读取磁盘中所有文件\文件夹名称
利用USN Journal相关函数
○1调用GetVolumeIformation()函数获取NTFS磁盘格式
GetVolumeInformation( lpRootPathName: PChar; // 磁盘驱动器代码字符串 lpVolumeNameBuffer: PChar; // 磁盘驱动器卷标名称 nVolumeNameSize: DWORD; // 磁盘驱动器卷标名称长度 lpVolumeSerialNumber: PDWORD; // 磁盘驱动器卷标序列号 var lpMaximumComponentLength: DWORD; // 系统允许的最大文件名长度 var lpFileSystemFlags: DWORD; // 文件系统标识 lpFileSystemNameBuffer: PChar; // 格式类型 nFileSystemNameSize: DWORD // 文件操作系统名称长度);
○2调用CreateFile()函数获取磁盘句柄
HANDLE hVol = CreateFile( "盘符字符串", // 必须如\.\C: (A-Z)的形式 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, // 必须包含有FILE_SHARE_WRITE NULL, OPEN_EXISTING, // 必须包含OPEN_EXISTING, CREATE_ALWAYS可能会导致错误 FILE_ATTRIBUTE_READONLY, // FILE_ATTRIBUTE_NORMAL可能会导致错误 NULL);
○3调用DeviceIoControl()函数读取USN Journal信息
BOOL DeviceIoControl(HANDLE hDevice, \\要操作的磁盘的句柄,通过CreatFile返回值DWORD dwIoControlCode,\\控制磁盘的指令 LPVOID lpInBuffer, \\磁盘操控请求数据的BufferDWORD nInBufferSize, \\ lpInBuffer的sizeLPVOID LpoutBuffer, \\存放输出数据的BufferDWORD nOutBufferSize, \\输出数据Buffer的sizeLPDWORD lpBytesReturned,\\实际输出数据的bytesLPOVERLAPPED lpOverlapped \\NULL);
用FSCTL_QUERY_USN_JOURNAL作为DeviceIoControl的控制代码。
lpOutBuffer返回一个 USN_JOURNAL_DATA,是一个结构体。
typedef struct { DWORDLONG UsnJournalID; USN FirstUsn; USN NextUsn; USN LowestValidUsn; USN MaxUsn; DWORDLONG MaximumSize; DWORDLONG AllocationDelta;} USN_JOURNAL_DATA, *PUSN_JOURNAL_DATA;
USN是以 USN_RECORD 形式储存的,其结构为:
typedef struct { DWORD RecordLength; // 记录长度 WORD MajorVersion; // 主版本 WORD MinorVersion; // 次版本 DWORDLONG FileReferenceNumber; // 文件引用数 DWORDLONG ParentFileReferenceNumber; // 父目录引用数 USN Usn; // USN LARGE_INTEGER TimeStamp; // 时间戳 DWORD Reason; // 原因 DWORD SourceInfo; // 源信息 DWORD SecurityId; // 安全 ID DWORD FileAttributes; // 文件属性 WORD FileNameLength; // 文件长度 WORD FileNameOffset; // 文件名偏移 DWORD ExtraInfo1; DWORD ExtraInfo2; DWORD ExtraInfo3; // Hypothetically added in version 2.3 WCHAR FileName[1]; // 文件名第一位的指针} USN_RECORD, *PUSN_RECORD;
具体实现代码如下:
DeviceIoControl() 与 FSCTL_ENUM_USN_DATA 配合。while (0!=DeviceIoControl(hVol, FSCTL_ENUM_USN_DATA, &med, sizeof (med), Buffer, BUF_LEN, &usnDataSize, NULL)) { DWORD dwRetBytes = usnDataSize - sizeof (USN); // 找到第一个 USN 记录 UsnRecord = (PUSN_RECORD)(((PCHAR)Buffer)+sizeof (USN)); while (dwRetBytes>0){ // 获取到的信息 CString CfileName(UsnRecord->FileName, UsnRecord->FileNameLength/2); pfrnName.filename = nameCur.filename = CfileName; pfrnName.pfrn = nameCur.pfrn = UsnRecord->ParentFileReferenceNumber; // Vector VecNameCur.push_back(nameCur); // 构建hash... frnPfrnNameMap[UsnRecord->FileReferenceNumber] = pfrnName; // 获取下一个记录 DWORD recordLen = UsnRecord->RecordLength; dwRetBytes -= recordLen; UsnRecord = (PUSN_RECORD)(((PCHAR)UsnRecord)+recordLen); } // 获取下一页数据 med.StartFileReferenceNumber = \*(USN \*)&Buffer;}/*其中,Med为:MFT_ENUM_DATA med; med.StartFileReferenceNumber = 0; med.LowUsn = 0;//UsnInfo.FirstUsn; 这里经测试发现,如果用FirstUsn有时候不正确,导致获取到不完整的数据,还是直接写0好. med.HighUsn = UsnInfo.NextUsn;在这个循环中,把每次获取到的文件名,分别插入vector与哈希表中。 */
注意:最后为了文件的安全性,需将USN Journal删除。(不删除也没问题)
二、构建查找数据的函数
○1构建Vector
typedef struct _name_cur { CString filename; DWORDLONG pfrn; }Name_Cur;用Vector来存放<文件名,当前目录>,由于模糊查找的要求,Vector从begin到end的线性遍历方式比较适用。○2用STL的map函数构建Hash Tabletypedef struct pfrn_name { DWORDLONG pfrn; CString filename;}Pfrn_Name;typedef map<DWORDLONG, Pfrn_Name> Frn_Pfrn_Name_Map;
○3插入到Vector和Hash Table中数据
在上边个获取USN Journal 文件的信息那个while循环中,把每次获取到的USN_RECORD信息,里面的filename, pfrn, frn分别插入到vector与Hash Table中。
pfrnName.filename = nameCur.filename = CfileName;pfrnName.pfrn = nameCur.pfrn = UsnRecord->ParentFileReferenceNumber;VecNameCur.push_back(nameCur);frnPfrnNameMap[UsnRecord->FileReferenceNumber] = pfrnName;
三、线程
一开始创建MFC时,顺序执行导致界面在全部数据统计结束后才能显示。之后采用AFxBeginThreade()函数建立两个线程,一个GUI线程,一个worker线程在后台统计数据。
四、界面
界面用MFC实现。
排除菜单:
1)考虑到有些文件夹被用来存放用户私密文件。
2)系统文件夹,例如:“c:\windows***”一般用户是用不到的,同等搜索只会增加不必要的文件,拖重系统负担。
排除菜单相应代码:
bool isIgnore( vector<string>\* pignorelist ) { string tmp = CW2A(path); for ( vector<string>::iterator it = pignorelist->begin(); it != pignorelist->end(); ++it ) { size_t i = it->length(); if ( !tmp.compare(0, i, \*it,0, i) ) { return true; } } return false; }
五、功能
Editbox :
得到用户输入的需要查找的字符串
Button :
1) 得到EditBox中的字符串
2) 字符太短弹出提示
3) 加上放大镜图片,功能一目了然
Listbox :
1) 显示匹配的文件名与路径,双击可打开文件
2) 由于路径可能比较长,加入水平滚动条
3) 双击Listbox中的结果文件路径,打开被双击选中的文件
- Windows快速检索文件MFC实例
- Windows下实现文件检索
- 文件读写实例(MFC)
- 过滤器实现快速检索资源文件
- MFC+FTP上传文件实例
- VC下利用多线程实现文件的快速检索
- VC下利用多线程实现文件的快速检索
- 读取NTFS的USN(快速检索文件)
- VC下利用多线程实现文件的快速检索
- windows 快速创建大文件
- 一系列MFC操作文件实例(上)
- 一系列MFC操作文件实例(中)
- MFC编程实例学习pdf文件
- Windows文件检索之——接口设计
- Windows文件检索之——查询条件
- Windows文件检索之——查询范围
- Windows文件检索、复制工具(Python Tkinter)
- 目录快速检索
- 第十一周oj题查闰年
- select poll epoll的区别
- linux 配置域名
- 数据库与MySQL(一)
- 封装好的Notification
- Windows快速检索文件MFC实例
- 使用VMware快速搭建几个Linux主机(网卡坏了也可参考)
- play framework 2.59 自定义多数据源 读取配置时报错
- Java web ——JAXB 技术—— 提供 javabean 和 xml 映射
- 常见的HTTP状态码(HTTP Status Code)说明
- 随着时间的长河向前走
- js数组去重
- In class programming 1
- 洛谷 P1759 通天之潜水