前两天在看linux内核代码,因为还没有很熟悉,有一些函数不知道在哪个文件里,手动找很麻烦,于是在windows下写了个文件搜索单词功能的小程序。只是实现了连续字母的搜索,也花了我两个小时写程序,后面第二天又测试调度了两个小时,今天第三天又用C++重写了这个功能;算是可以使用,放出来分享一下,如果有bug,请帮忙报告一下。
1. 说明一下类CFindWord的功能:先使用Init函数附带folder参数指定目标文件夹,使用filter参数指定需要过滤的文件扩展名;这个函数把文件下所有符合过滤条件的文件中的所有单词统计位置,算是一个初始化工作;然后使用Find函数查找对应的单词在哪个文件哪一行出现过;如果需要打印则调用PrintResult;我在后面贴了一个使用例子。
2. 说明一下功能特点:可以使用Unicode或多字节编译运行;第一次初始化需要的时间比较长一点,我对linux0.11的代码4m左右初始化需要1秒左右,如果太多文件,可能需要比较长的时间。第一次初始化会解析好过滤文件名,搜索每个文件,建立文件字典;搜索文件的每行每个单词,建立单词字典;并把每个单词对应的文件ID及行号,行的内容记录;形成一个可以快速查询的综合字典,因为使用了字符串hash,所以搜索效率可以到达O(1);但没有完全测试hash碰撞情况,不排除因碰撞产生搜索结果不正确的情况。
3. 说明一下功能限制:在FindWordInLine函数中可以看出,我只实现了对字符组成的单词全字匹配,如果想加其他功能,可以在FindWordInLine这个函数里面改;比如做一些正则的匹配等。我目前对单词目标比较明确,目前没有实现正则。
4. 后期可能做的就是,加一个小界面,在windows下可以使用快捷键快速调出窗口,指定文件夹,输入单词,快速列出结果。另外,也应该实现非单词形式的字符串的搜索功能。
#pragma once
#include <vector>
#include <stack>
#include <string>
#include <list>
#include <map>
// 为了支持宽字节或多字节流做的宏
#ifdef _UNICODE
#define tstring wstring
#define tifstream wifstream
#define tcout wcout
#else
#define tstring string
#define tifstream ifstream
#define tcout cout
#endif
typedef struct
{
DWORD fileid;
DWORD linenumber;
std::tstring linecontent;
}findresult;
class CFindWord
{
public:
CFindWord(){};
~CFindWord(){};
// 使用此函数指定目标文件夹和过滤文件的扩展名初化文件表和词表数据
bool Init(const std::tstring &folder,const std::tstring &filter);
// 从已初始化好的数据中搜索对应单词结果
DWORD Find(const std::tstring &word,std::list<findresult> &listfindresult);
// 供测试打印用,与程序逻辑无关
void PrintResult(std::list<findresult> &listfindresult);
private:
// 利用hash值来快速比较字符串值
DWORD CalcStringToHash(const TCHAR * key,DWORD len);
// 检测文件是否是过滤的扩展名
bool IsFilteFile(std::tstring &fullpath);
// 取得文件列表
DWORD GetFileList(LPCTSTR in_directory,WIN32_FIND_DATA * out_path_list, DWORD in_max_path_list_count);
// 递归取得文件夹内所有文件
DWORD RecurseGetFile(std::stack<std::tstring> &stack_path,std::list<std::tstring> &list_file);
DWORD FindInFolder(const std::tstring &folder);