C++实现文件搜索小工具

文件快速定位器:可支持 1) 文件名(全部汉字或部分汉字),2) 文件名拼音,3)  文件名首字母,4)汉字和拼音, 汉字和首字母混在一起的搜索。 功能:输入要搜索文件,在终端上显示出相匹配的文件名和文件所在路径。

一、项目背景

背景:Linux环境下有find命令,用来查找文件便捷高效,而windows下文件框的默认搜索是搜索时再进行暴力查找,非常的慢,不能进行全局搜索,对于长时间不用记不清名字的文件来说,查找非常困难。

因此此文中的文件快速定位器是在搜索软件Everything的基础上结合QQ,百度等搜索工具的部分功能的基础上来实现的。

调查:如下图everything搜索软件界面和实现功能,它将文档信息检索以后,先存到数据库,查找时在数据库进行搜索,速度就快了很多(数据库中文件存储的底层数据结构为红黑树或者哈希表),软件实现了按文件名关键字的查找。

QQ等软件中的搜索可支持汉字搜索,拼音搜索,首字母搜索,并做到关键字高亮处理。

实现:

文件快速定位器:在windows下实现指定路径下文件的汉字搜索、拼音搜索、首字母搜索并高亮显示搜索出来的关键字。即:在输入要查找的文件关键字,在终端上打印出包含关键字的文件名和文件路径,并高亮显示关键字

汉字搜索:第二次课

拼音搜索:diercike

首字母搜索: DECK

二、项目框架

1.数据扫描模块(扫描+监控)

    1)扫描:获取指定路径下的所有文档

把给定路径下的文档的名称的路径扫描出来,放到容器里面等待处理。

使用C语言下#include <io.h>中的接口_findfirst  _findnext来查找文件,_findfirst  _findnext的使用方法、接口参数设置和返回值详细参考博文:https://blog.csdn.net/damant/article/details/50833845

    2)监控:本地与数据库文件对比

2.数据持久化

    1)数据库使用

使用轻量级的数据库sqlit 3,数据库简介 https://www.runoob.com/sqlite/sqlite-intro.html

数据库官网:https://www.sqlite.org/index.html

数据库的打开、关闭、创建表格、SQL语句执行

创建一张供搜索用的表即可

create table if not exists %s (id INTEGER PRIMARY KEY, path text, name text,
name_pinyin text, name_initials text);

    2)数据管理

数据库初始化、建表、增加或删除数据

3.搜索

   汉字、拼音和首字母搜索。采用数据库Like语句实现模糊匹配检索

高亮显示。自主实现高亮算法

4.其他套用模块

trace日志模块(记录错误,找到出错点 返回错误码)

高亮打印一段字符串

汉字转拼音全拼(UTF-8)

    汉字转拼音首字母(UTF-8)

三、数据扫描模块

1.扫描指定路径下文件(_findfirst  _findnext

static void DirectoryList(const string& path, vector<string>& dirs, vector<string>& files)
{   _finddata_t file;  //存放文件信息的结构体的指针const string path_ = path + "\\*.*";   //此符号为遍历path下的所有文档,路径格式intptr_t handle = _findfirst(path_.c_str(), &file);  //返回查找用的句柄if (handle == -1){cout << "_findfirst: " << path << "error" << endl;return;}do{//_A_ARCH(存档)_A_HIDDEN(隐藏)_A_NORMAL(正常)_A_RDONLY(只读)_A_SUBDIR(文件夹)//_A_SYSTEM(系统)if (file.attrib & _A_SUBDIR)   //判断此目录为文件夹可递归进去{if ((strcmp(file.name, ".") != 0) && (strcmp(file.name, "..") != 0)){       //存放文件夹等目录文件dirs.push_back(file.name);}}else{       //存放最终文件files.push_back(file.name);}} while (_findnext(handle, &file) == 0);
}

2.扫描模块管理

//ScanManager设计成单例,整个程序只有一个扫描模块
//多线程执行扫描
class ScanManager
{
public:void Scan(const string& path);  //扫描对比 文件系统和数据库的文件void StartScan(){while (1){Scan("F:\\bite学习");   //设定扫描目录std::this_thread::sleep_for(std::chrono::seconds(5)); //5s扫一次}}static ScanManager* CreateIntance(){static ScanManager scanmgr;static std::thread thd(&StartScan, &scanmgr);thd.detach();return &scanmgr;}
private:ScanManager()  //构造函数私有化{}ScanManager(const ScanManager&);//vector<string> entrys;  //多线程多个目录遍历扫
};

扫描模块设定成单例模式,使整个项目只有一个扫描模块,线程持续重复扫描指定目录。

扫描模块具体实现

void ScanManager::Scan(const string& path)
{//比对 文件系统和数据库vector<string> localdirs;     //目录vector<string> localfiles;    //文件DirectoryList(path, localdirs, localfiles);  //获取path下所有文件信息std::set<string> localset;localset.insert(localfiles.begin(), localfiles.end());localset.insert(localdirs.begin(), localdirs.end());//写入set里内部排序比对std::set<string> dbset;   //DataManagerDataManager::GetInstance()->GetDoc(path, dbset);  //查看数据库里的数据auto localit = localset.begin();auto dbit = dbset.begin();while (localit != localset.end() && dbit != dbset.end()){if (*localit < *dbit)  //本地右,数据没有  -> 给数据库增加数据{//数据库新增数据DataManager::GetInstance()->InsertDoc(path, *localit);++localit;}else if (*localit > *dbit)  //本地没有,数据库有  -> 删除数据库中的数据{//数据库中数据删除DataManager::GetInstance()->DeleteDoc(path, *dbit);++dbit;}else{++localit;++dbit;}}while (localit != localset.end()){//数据库新增数据DataManager::GetInstance()->InsertDoc(path, *localit);++localit;}while (dbit != dbset.end()){//删除数据库中数据DataManager::GetInstance()->DeleteDoc(path, *dbit);++dbit;}//递归扫描对比子目录数据for (const auto& subdirs : localdirs){string subpath = path;subpath += '\\';subpath += subdirs;  //搜索path下的子目录绝对路径Scan(subpath);       //递归比对子目录的所有文件}
}

把本地和数据库中的文件信息放入set(自动排序)里面,根据两个set里的数据迭代器对比,本地有数据库没有,数据库新增数据;本地没有数据库有,数据库删除数据;  递归对比所有子目录下的文件。

四、数据持久化

把数据放入数据库(本项目选用轻量级数据库sqlite 3),在数据库的基础上处理数据。

1.数据库的使用

    1)添加外部库文件(sqlite 3)

       使用外部编辑下载好的sqlite3.h文件

#include "./sqlite-amalgamation-3280000/sqlite3.h"  //链接sqlite数据库

首先,把库文件放到工程目录下,然后,在VS 2013工程下的解决方案资源管理器中 ->工程名 -> 属性 -> 链接器/常规 -> 附加库目录(添加外部库的路径)  ->  点击输入项 -> 附加依赖项(添加上sqlite3.h文件)。

操作数据库:

class SqliteManager {
public:SqliteManager():_db(nullptr){}~SqliteManager(){Close();}void Open(const string& path);void Close();void ExecuteSql(const string& sql);//采用RAII  实现 打开数据库后的自动关闭void GetTable(const string& sql, int& row, int& col, char**& ppRet);SqliteManager(const SqliteManager&) = delete;SqliteManager& operator=(const SqliteManager&) = delete;
private:sqlite3* _db;       // 数据库对象
};
//RAII
//来代替数据库的主动释放
class AutoGetTable
{
public:AutoGetTable(SqliteManager& sm, const string& sql, int& row, int& col, char**& ppRet){sm.GetTable(sql, row, col, ppRet);_ppRet = ppRet;}~AutoGetTable(){sqlite3_free_table(_ppRet);}AutoGetTable(const AutoGetTable&) = delete;             //防止两个对象释放一个AutoGetTable& operator=(const AutoGetTable&) = delete;  //防拷贝,模拟c++11 uniqueptr 的实现private:char** _ppRet;
};

实现数据库的打开、执行、关闭。 使用RAII来主动创建数据库,并free数据库,避免出现没存泄露。

2.数据库数据管理

数据库中数据的管理包括:数据库初始化(打开),获取数据库中的数据,数据库中插入删除数据,关键字搜索,关键字高亮。

//为方便加锁,设计成单例模式
class DataManager
{
public:static DataManager* GetInstance(){static DataManager datamgr;datamgr.Init();return &datamgr;}void Init();   //建表,打开数据库void GetDoc(const string& path, std::set<string>& dbset);  //查找path下的所有子文档void InsertDoc(const string& path, const string& name);void DeleteDoc(const string& path, const string& name);void Search(const string& key, vector<std::pair<string, string>>& docinfos);void SetHightLight(const string& str, const string& key, string& prefix, string& highlight, string& suffix);private:DataManager()   //构造函数私有{}SqliteManager _dbmgr;std::mutex _mtx;
};

设计成单例模式,保证同一时间只进行几次数据库操作,防止数据丢失或多余。

五、关键字搜索高亮处理

1.关键字搜索

包括:汉字搜索、汉字拼音全拼搜索、汉字拼音首字母搜索。

使用SQL语句中的like模糊匹配功能实现: 由于编译环境和windows系统都 采用UTF-8中文编码,与数据库编码方式不同,所以汉字存入数据库中换出现乱码现象,而编码转换过于复杂,因此,此处搜索部分对汉字的搜索都通过把汉字转换成汉字全拼或拼音首字母来进行like模糊匹配

//拼音匹配搜索
select name, path from %s where name_pinyin like '%%%s%%';
//拼音首字母like匹配搜索
select name, path from %s where name_initials like '%%%s%%';

搜索实现代码如下:

//搜索开始
void DataManager::Search(const string& key, vector<std::pair<string, string>>& docinfos)
{char sql[256] = { '\0' };{       //拼音搜索string pinyin = ChineseConvertPinYinAllSpell(key);//首字母搜索string initials = ChineseConvertPinYinInitials(key);  sprintf(sql, "select name, path from %s where name_pinyin or name_initials like '%%%s%%' or '%%%s%%'", TB_NAME, pinyin.c_str(), initials.c_str());int row, col;char** ppRet;AutoGetTable agt(_dbmgr, sql, row, col, ppRet);for (int i = 1; i <= row; i++){docinfos.push_back(std::make_pair(ppRet[i * col], ppRet[i * col + 1]));}}
}

2.关键字高亮

对一串字符串中的某段关键字字符串高亮显示,实现高亮算法,并借助高亮实现函数来实现。

1)针对查找关键字为汉字的高亮

//1. key 是原串字串{       //原串中查找关键字的位置size_t ht_start = str.find(key);if (ht_start != string::npos){       prefix = str.substr(0, ht_start);//关键字前的串highlight = key;  //高亮关键字suffix = str.substr(ht_start + key.size(), string::npos);//关键字后的串return;}}

2)针对查找关键字为汉字的拼音全拼的高亮

//2. key是搜索部分串的全拼{string key_ap = ChineseConvertPinYinAllSpell(key);string str_ap = ChineseConvertPinYinAllSpell(str);   //ap 代表 allspellsize_t ht_index = 0;size_t ap_index = 0;size_t ht_start = 0, ht_len = 0;size_t ap_start = str_ap.find(key);        //高亮部分的起点if (ap_start != string::npos){size_t ap_end = ap_start + key_ap.size();  //高亮部分的终点while (ap_index < ap_end){if (ap_index == ap_start){ht_start = ht_index;}if (str[ht_index] >= 0 && str[ht_index] <= 127){++ht_index;++ap_index;}else{char chinese[3] = { '\0' };chinese[0] = str[ht_index];chinese[1] = str[ht_index + 1];ht_index += 2;     //跳过一个汉字的长度  //gbk 编码汉字占两个字节string ap_str = ChineseConvertPinYinAllSpell(chinese);ap_index += ap_str.size();  //跳过一个汉字拼音的长度}}ht_len = ht_index - ht_start;prefix = str.substr(0, ht_start);highlight = str.substr(ht_start, ht_len);suffix = str.substr(ht_start + ht_len, string::npos);return;}}

算法具体实现:

3)针对查找关键字为汉字的拼音全拼的首字母的高亮

//3. key是拼音首字母{string init_str = ChineseConvertPinYinInitials(str);string init_key = ChineseConvertPinYinInitials(key);size_t init_start = init_str.find(init_key);if (init_start != string::npos){size_t init_end = init_start + init_key.size();size_t init_index = 0, ht_index = 0;size_t ht_start = 0, ht_len = 0;while (init_index < init_end){if (init_index == init_start){ht_start = ht_index;}//字符if (str[ht_index] >= 0 && str[ht_index] <= 127){++ht_index;++init_index;}else //汉字{ht_index += 2;++init_index;}}ht_len = ht_index - ht_start;prefix = str.substr(0, ht_start);highlight = str.substr(ht_start, ht_len);suffix = str.substr(ht_start + ht_len, string::npos);return;}}ERROE_LOG("spilt highlight no match. str:%s, key:%s\n", str.c_str(), key.c_str());prefix = str;
}

算法具体实现:

六、套用模块

1.trace日志:

//trace日志   找到出错点,返回错误码
static std::string GetFileName(const std::string& path)
{char ch = '/';#ifdef _WIN32    ch = '\\';
#endif    size_t pos = path.rfind(ch);if (pos == std::string::npos)return path;elsereturn path.substr(pos + 1);
}//用于调试追溯的trace log
inline static void __TraceDebug(const char* filename, int line, const char* function, const char* format, ...)
{
#ifdef __TRACE__    //输出调用函数的信息    fprintf(stdout, "[TRACE][%s:%d:%s]:", GetFileName(filename).c_str(), line, function);//输出用户打的trace信息    va_list args;va_start(args, format);vfprintf(stdout, format, args);va_end(args);fprintf(stdout, "\n");
#endif
}inline static void __ErrorDebug(const char* filename, int line, const char* function, const char* format, ...)
{
#ifdef __DEBUG__    //输出调用函数的信息    fprintf(stdout, "[ERROR][%s:%d:%s]:", GetFileName(filename).c_str(), line, function);//输出用户打的trace信息    va_list args;va_start(args, format);vfprintf(stdout, format, args);va_end(args);fprintf(stdout, " errmsg:%s, errno:%d\n", strerror(errno), errno);
#endif
}#define TRACE_LOG(...) \__TraceDebug(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__);#define ERROE_LOG(...) \__ErrorDebug(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__);

2.高亮打印一段字符串str

static void ColourPrintf(const char* str)
{// 0-黑 1-蓝 2-绿 3-浅绿 4-红 5-紫 6-黄 7-白 8-灰 9-淡蓝 10-淡绿// 11-淡浅绿 12-淡红 13-淡紫 14-淡黄 15-亮白//颜色:前景色 + 背景色*0x10 //例如:字是红色,背景色是白色,即 红色 + 亮白 = 4 + 15*0x10 WORD color = 5 + 6 * 0x10;WORD colorOld;HANDLE handle = ::GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_SCREEN_BUFFER_INFO csbi;GetConsoleScreenBufferInfo(handle, &csbi);colorOld = csbi.wAttributes;SetConsoleTextAttribute(handle, color);printf("%s", str);SetConsoleTextAttribute(handle, colorOld);
}

3.汉字转拼音全拼

/*
* CSDN:http://blog.csdn.net/csnd_ayo
*/
static string ChineseConvertPinYinAllSpell(const std::string& dest_chinese)
{static const int spell_value[] = { -20319, -20317, -20304, -20295, -20292, -20283,-20265, -20257, -20242, -20230, -20051, -20036, -20032, -20026,-20002, -19990, -19986, -19982, -19976, -19805, -19784, -19775, -19774, -19763,-19756, -19751, -19746, -19741, -19739, -19728,-19725, -19715, -19540, -19531, -19525, -19515, -19500, -19484, -19479, -19467,-19289, -19288, -19281, -19275, -19270, -19263,-19261, -19249, -19243, -19242, -19238, -19235, -19227, -19224, -19218, -19212,-19038, -19023, -19018, -19006, -19003, -18996,-18977, -18961, -18952, -18783, -18774, -18773, -18763, -18756, -18741, -18735,-18731, -18722, -18710, -18697, -18696, -18526,-18518, -18501, -18490, -18478, -18463, -18448, -18447, -18446, -18239, -18237,-18231, -18220, -18211, -18201, -18184, -18183,-18181, -18012, -17997, -17988, -17970, -17964, -17961, -17950, -17947, -17931,-17928, -17922, -17759, -17752, -17733, -17730,-17721, -17703, -17701, -17697, -17692, -17683, -17676, -17496, -17487, -17482,-17468, -17454, -17433, -17427, -17417, -17202,-17185, -16983, -16970, -16942, -16915, -16733, -16708, -16706, -16689, -16664,-16657, -16647, -16474, -16470, -16465, -16459,-16452, -16448, -16433, -16429, -16427, -16423, -16419, -16412, -16407, -16403,-16401, -16393, -16220, -16216, -16212, -16205,-16202, -16187, -16180, -16171, -16169, -16158, -16155, -15959, -15958, -15944,-15933, -15920, -15915, -15903, -15889, -15878,-15707, -15701, -15681, -15667, -15661, -15659, -15652, -15640, -15631, -15625,-15454, -15448, -15436, -15435, -15419, -15416,-15408, -15394, -15385, -15377, -15375, -15369, -15363, -15362, -15183, -15180,-15165, -15158, -15153, -15150, -15149, -15144,-15143, -15141, -15140, -15139, -15128, -15121, -15119, -15117, -15110, -15109,-14941, -14937, -14933, -14930, -14929, -14928,-14926, -14922, -14921, -14914, -14908, -14902, -14894, -14889, -14882, -14873,-14871, -14857, -14678, -14674, -14670, -14668,-14663, -14654, -14645, -14630, -14594, -14429, -14407, -14399, -14384, -14379,-14368, -14355, -14353, -14345, -14170, -14159,-14151, -14149, -14145, -14140, -14137, -14135, -14125, -14123, -14122, -14112,-14109, -14099, -14097, -14094, -14092, -14090,-14087, -14083, -13917, -13914, -13910, -13907, -13906, -13905, -13896, -13894,-13878, -13870, -13859, -13847, -13831, -13658,-13611, -13601, -13406, -13404, -13400, -13398, -13395, -13391, -13387, -13383,-13367, -13359, -13356, -13343, -13340, -13329,-13326, -13318, -13147, -13138, -13120, -13107, -13096, -13095, -13091, -13076,-13068, -13063, -13060, -12888, -12875, -12871,-12860, -12858, -12852, -12849, -12838, -12831, -12829, -12812, -12802, -12607,- 12597, -12594, -12585, -12556, -12359, -12346,-12320, -12300, -12120, -12099, -12089, -12074, -12067, -12058, -12039, -11867,-11861, -11847, -11831, -11798, -11781, -11604,-11589, -11536, -11358, -11340, -11339, -11324, -11303, -11097, -11077, -11067,-11055, -11052, -11045, -11041, -11038, -11024,-11020, -11019, -11018, -11014, -10838, -10832, -10815, -10800, -10790, -10780,-10764, -10587, -10544, -10533, -10519, -10331,-10329, -10328, -10322, -10315, -10309, -10307, -10296, -10281, -10274, -10270,-10262, -10260, -10256, -10254 };// 395个字符串,每个字符串长度不超过6static const char spell_dict[396][7] = { "a", "ai", "an", "ang", "ao", "ba", "bai","ban", "bang", "bao", "bei", "ben", "beng", "bi", "bian", "biao","bie", "bin", "bing", "bo", "bu", "ca", "cai", "can", "cang", "cao", "ce", "ceng","cha", "chai", "chan", "chang", "chao", "che", "chen","cheng", "chi", "chong", "chou", "chu", "chuai", "chuan", "chuang", "chui", "chun","chuo", "ci", "cong", "cou", "cu", "cuan", "cui","cun", "cuo", "da", "dai", "dan", "dang", "dao", "de", "deng", "di", "dian","diao", "die", "ding", "diu", "dong", "dou", "du", "duan","dui", "dun", "duo", "e", "en", "er", "fa", "fan", "fang", "fei", "fen", "feng","fo", "fou", "fu", "ga", "gai", "gan", "gang", "gao","ge", "gei", "gen", "geng", "gong", "gou", "gu", "gua", "guai", "guan", "guang","gui", "gun", "guo", "ha", "hai", "han", "hang","hao", "he", "hei", "hen", "heng", "hong", "hou", "hu", "hua", "huai", "huan","huang", "hui", "hun", "huo", "ji", "jia", "jian","jiang", "jiao", "jie", "jin", "jing", "jiong", "jiu", "ju", "juan", "jue", "jun","ka", "kai", "kan", "kang", "kao", "ke", "ken","keng", "kong", "kou", "ku", "kua", "kuai", "kuan", "kuang", "kui", "kun", "kuo","la", "lai", "lan", "lang", "lao", "le", "lei","leng", "li", "lia", "lian", "liang", "liao", "lie", "lin", "ling", "liu", "long","lou", "lu", "lv", "luan", "lue", "lun", "luo","ma", "mai", "man", "mang", "mao", "me", "mei", "men", "meng", "mi", "mian","miao", "mie", "min", "ming", "miu", "mo", "mou", "mu","na", "nai", "nan", "nang", "nao", "ne", "nei", "nen", "neng", "ni", "nian","niang", "niao", "nie", "nin", "ning", "niu", "nong","nu", "nv", "nuan", "nue", "nuo", "o", "ou", "pa", "pai", "pan", "pang", "pao","pei", "pen", "peng", "pi", "pian", "piao", "pie","pin", "ping", "po", "pu", "qi", "qia", "qian", "qiang", "qiao", "qie", "qin","qing", "qiong", "qiu", "qu", "quan", "que", "qun","ran", "rang", "rao", "re", "ren", "reng", "ri", "rong", "rou", "ru", "ruan","rui", "run", "ruo", "sa", "sai", "san", "sang","sao", "se", "sen", "seng", "sha", "shai", "shan", "shang", "shao", "she", "shen","sheng", "shi", "shou", "shu", "shua","shuai", "shuan", "shuang", "shui", "shun", "shuo", "si", "song", "sou", "su","suan", "sui", "sun", "suo", "ta", "tai","tan", "tang", "tao", "te", "teng", "ti", "tian", "tiao", "tie", "ting", "tong","tou", "tu", "tuan", "tui", "tun", "tuo","wa", "wai", "wan", "wang", "wei", "wen", "weng", "wo", "wu", "xi", "xia", "xian","xiang", "xiao", "xie", "xin", "xing","xiong", "xiu", "xu", "xuan", "xue", "xun", "ya", "yan", "yang", "yao", "ye", "yi","yin", "ying", "yo", "yong", "you","yu", "yuan", "yue", "yun", "za", "zai", "zan", "zang", "zao", "ze", "zei", "zen","zeng", "zha", "zhai", "zhan", "zhang","zhao", "zhe", "zhen", "zheng", "zhi", "zhong", "zhou", "zhu", "zhua", "zhuai","zhuan", "zhuang", "zhui", "zhun", "zhuo","zi", "zong", "zou", "zu", "zuan", "zui", "zun", "zuo" };std::string pinyin;// 循环处理字节数组const int length = dest_chinese.length();for (int j = 0, chrasc = 0; j < length;) {// 非汉字处理if (dest_chinese.at(j) >= 0 && dest_chinese.at(j) < 128) {pinyin += dest_chinese[j];// 偏移下标j++;continue;}// 汉字处理chrasc = dest_chinese[j] * 256 + dest_chinese[j + 1] + 256;if (chrasc > 0 && chrasc < 160) {// 非汉字pinyin += dest_chinese.at(j);// 偏移下标j++;}else {// 汉字for (int i = (sizeof(spell_value) / sizeof(spell_value[0]) - 1); i >= 0; --i) {// 查找字典if (spell_value[i] <= chrasc) {pinyin += spell_dict[i];break;}}// 偏移下标 (汉字双字节)j += 2;}} // for endreturn pinyin;
}

4.汉字转拼音首字母

static std::string ChineseConvertPinYinInitials(const std::string& name)
{// 仅生成拼音首字母内容static int secPosValue[] = {1601, 1637, 1833, 2078, 2274, 2302, 2433, 2594, 2787, 3106, 3212,3472, 3635, 3722, 3730, 3858, 4027, 4086, 4390, 4558, 4684, 4925, 5249};static const char* initials[] = {"a", "b", "c", "d", "e", "f", "g", "h", "j", "k", "l", "m", "n", "o","p", "q", "r", "s", "t", "w", "x", "y", "z"};static const char* secondSecTable ="CJWGNSPGCGNE[Y[BTYYZDXYKYGT[JNNJQMBSGZSCYJSYY[PGKBZGY[YWJKGKLJYWKPJQHY[W[DZLSGMRYPYWWCCKZNKYYGTTNJJNYKKZYTCJNMCYLQLYPYQFQRPZSLWBTGKJFYXJWZLTBNCXJJJJTXDTTSQZYCDXXHGCK[PHFFSS[YBGXLPPBYLL[HLXS[ZM[JHSOJNGHDZQYKLGJHSGQZHXQGKEZZWYSCSCJXYEYXADZPMDSSMZJZQJYZC[J[WQJBYZPXGZNZCPWHKXHQKMWFBPBYDTJZZKQHY""LYGXFPTYJYYZPSZLFCHMQSHGMXXSXJ[[DCSBBQBEFSJYHXWGZKPYLQBGLDLCCTNMAYDDKSSNGYCSGXLYZAYBNPTSDKDYLHGYMYLCXPY[JNDQJWXQXFYYFJLEJPZRXCCQWQQSBNKYMGPLBMJRQCFLNYMYQMSQYRBCJTHZTQFRXQHXMJJCJLXQGJMSHZKBSWYEMYLTXFSYDSWLYCJQXSJNQBSCTYHBFTDCYZDJWYGHQFRXWCKQKXEBPTLPXJZSRMEBWHJLBJSLYYSMDXLCLQKXLHXJRZJMFQHXHWY""WSBHTRXXGLHQHFNM[YKLDYXZPYLGG[MTCFPAJJZYLJTYANJGBJPLQGDZYQYAXBKYSECJSZNSLYZHSXLZCGHPXZHZNYTDSBCJKDLZAYFMYDLEBBGQYZKXGLDNDNYSKJSHDLYXBCGHXYPKDJMMZNGMMCLGWZSZXZJFZNMLZZTHCSYDBDLLSCDDNLKJYKJSYCJLKWHQASDKNHCSGANHDAASHTCPLCPQYBSDMPJLPZJOQLCDHJJYSPRCHN[NNLHLYYQYHWZPTCZGWWMZFFJQQQQYXACLBHKDJXDGMMY""DJXZLLSYGXGKJRYWZWYCLZMSSJZLDBYD[FCXYHLXCHYZJQ[[QAGMNYXPFRKSSBJLYXYSYGLNSCMHZWWMNZJJLXXHCHSY[[TTXRYCYXBYHCSMXJSZNPWGPXXTAYBGAJCXLY[DCCWZOCWKCCSBNHCPDYZNFCYYTYCKXKYBSQKKYTQQXFCWCHCYKELZQBSQYJQCCLMTHSYWHMKTLKJLYCXWHEQQHTQH[PQ[QSCFYMNDMGBWHWLGSLLYSDLMLXPTHMJHWLJZYHZJXHTXJLHXRSWLWZJCBXMHZQXSDZP""MGFCSGLSXYMJSHXPJXWMYQKSMYPLRTHBXFTPMHYXLCHLHLZYLXGSSSSTCLSLDCLRPBHZHXYYFHB[GDMYCNQQWLQHJJ[YWJZYEJJDHPBLQXTQKWHLCHQXAGTLXLJXMSL[HTZKZJECXJCJNMFBY[SFYWYBJZGNYSDZSQYRSLJPCLPWXSDWEJBJCBCNAYTWGMPAPCLYQPCLZXSBNMSGGFNZJJBZSFZYNDXHPLQKZCZWALSBCCJX[YZGWKYPSGXFZFCDKHJGXDLQFSGDSLQWZKXTMHSBGZMJZRGLYJB""PMLMSXLZJQQHZYJCZYDJWBMYKLDDPMJEGXYHYLXHLQYQHKYCWCJMYYXNATJHYCCXZPCQLBZWWYTWBQCMLPMYRJCCCXFPZNZZLJPLXXYZTZLGDLDCKLYRZZGQTGJHHGJLJAXFGFJZSLCFDQZLCLGJDJCSNZLLJPJQDCCLCJXMYZFTSXGCGSBRZXJQQCTZHGYQTJQQLZXJYLYLBCYAMCSTYLPDJBYREGKLZYZHLYSZQLZNWCZCLLWJQJJJKDGJZOLBBZPPGLGHTGZXYGHZMYCNQSYCYHBHGXKAMTX""YXNBSKYZZGJZLQJDFCJXDYGJQJJPMGWGJJJPKQSBGBMMCJSSCLPQPDXCDYYKY[CJDDYYGYWRHJRTGZNYQLDKLJSZZGZQZJGDYKSHPZMTLCPWNJAFYZDJCNMWESCYGLBTZCGMSSLLYXQSXSBSJSBBSGGHFJLYPMZJNLYYWDQSHZXTYYWHMZYHYWDBXBTLMSYYYFSXJC[DXXLHJHF[SXZQHFZMZCZTQCXZXRTTDJHNNYZQQMNQDMMG[YDXMJGDHCDYZBFFALLZTDLTFXMXQZDNGWQDBDCZJDXBZGS""QQDDJCMBKZFFXMKDMDSYYSZCMLJDSYNSBRSKMKMPCKLGDBQTFZSWTFGGLYPLLJZHGJ[GYPZLTCSMCNBTJBQFKTHBYZGKPBBYMTDSSXTBNPDKLEYCJNYDDYKZDDHQHSDZSCTARLLTKZLGECLLKJLQJAQNBDKKGHPJTZQKSECSHALQFMMGJNLYJBBTMLYZXDCJPLDLPCQDHZYCBZSCZBZMSLJFLKRZJSNFRGJHXPDHYJYBZGDLQCSEZGXLBLGYXTWMABCHECMWYJYZLLJJYHLG[DJLSLYGKDZPZXJ""YYZLWCXSZFGWYYDLYHCLJSCMBJHBLYZLYCBLYDPDQYSXQZBYTDKYXJY[CNRJMPDJGKLCLJBCTBJDDBBLBLCZQRPPXJCJLZCSHLTOLJNMDDDLNGKAQHQHJGYKHEZNMSHRP[QQJCHGMFPRXHJGDYCHGHLYRZQLCYQJNZSQTKQJYMSZSWLCFQQQXYFGGYPTQWLMCRNFKKFSYYLQBMQAMMMYXCTPSHCPTXXZZSMPHPSHMCLMLDQFYQXSZYYDYJZZHQPDSZGLSTJBCKBXYQZJSGPSXQZQZRQTBDKYXZK"       "HHGFLBCSMDLDGDZDBLZYYCXNNCSYBZBFGLZZXSWMSCCMQNJQSBDQSJTXXMBLTXZCLZSHZCXRQJGJYLXZFJPHYMZQQYDFQJJLZZNZJCDGZYGCTXMZYSCTLKPHTXHTLBJXJLXSCDQXCBBTJFQZFSLTJBTKQBXXJJLJCHCZDBZJDCZJDCPRNPQCJPFCZLCLZXZDMXMPHJSGZGSZZQLYLWTJPFSYASMCJBTZKYCWMYTCSJJLJCQLWZMALBXYFBPNLSFHTGJWEJJXXGLLJSTGSHJQLZFKCGNNNSZFDEQ"     "FHBSAQTGYLBXMMYGSZLDYDQMJJRGBJTKGDHGKBLQKBDMBYLXWCXYTTYBKMRTJZXQJBHLMHMJJZMQASLDCYXYQDLQCAFYWYXQHZ";const char* cName = name.c_str();std::string result;int H = 0, L = 0, W = 0, j = 0;size_t stringlen = ::strlen(cName);for (int i = 0; i < stringlen; ++i) {H = (unsigned char)(cName[i + 0]);L = (unsigned char)(cName[i + 1]);if (H < 0xA1 || L < 0xA1) {result += cName[i];continue;}W = (H - 160) * 100 + L - 160;if (W > 1600 && W < 5590) {bool has = false;for (j = 22; j >= 0; j--) {if (W >= secPosValue[j]) {result += initials[j];i++;has = true;break;}}continue;}i++;W = (H - 160 - 56) * 94 + L - 161;if (W >= 0 && W <= 3007)result += secondSecTable[W];else {result += (unsigned char)H;result += (unsigned char)L;}}return result;
}

七、项目总结及日后完善点

1.项目开发工具:VS2013

测试平台:windows 10

2.功能:实现通过输出关键字,来查找指定目录下的所有含关键字的文件名,并最终在终端上打印出文件名和路径,此处支持汉字搜索、汉字拼音全拼搜索、汉字拼音首字母搜索,并在搜索出的文件名中高亮显示关键字。

3.项目开发模块:扫描(文件扫描和监控)模块、数据库管理模块、搜索模块、高亮显示算法模块、汉字转拼音、汉字转首字母模块、trace日志等。

4.项目开发亮点:sqlite3使用、采用RAII操作数据库、单例模式、高亮匹配算法、C++11的thread/mutex使用。

5.项目的不足:1)扫描大目录时,效率低,导致实际数据和搜索数据不一致。2)由于编码问题,使用拼音模糊搜索,搜索时出现小bug,搜索结果出现问题。

6.项目改进:对大目录进行多线程分片扫描,并加入监控模块。  解决编码问题。 多次测试使搜索结果更加准确等。

八、项目完整代码

此处附上GitHub代码链接,需要参考的伙伴,可以去看看。

感谢各位大佬指正与批评!

文件快速定位神器(C++小项目实战)相关推荐

  1. android简单app实例_Android安卓小项目实战视频教程集锦

    Android安卓小项目实战视频教程,点击进入视频教程: 一.安卓项目视频教程: 1蓝牙聊天APP介绍-分步骤介绍一个简单安卓蓝牙APP的开发过程 - 西瓜视频 2蓝牙聊天开发流程-分步骤介绍一个简单 ...

  2. 【分享-windows文件快速搜索神器】Everything 免费、快速搜索文件/文件夹

    windows文件快速搜索神器 - Everything 下载:https://www.voidtools.com/ 先来体验一波 windows自带的搜索如下,等了一分钟还没搜索完: Everyth ...

  3. CSS样式小项目实战 - 网页变色小按钮

    小项目练手实战 - 变色小按钮 [背景分析] 为了满足用户体验,提高项目网页的视觉冲击力,各大网站上都有一些有颜色的按钮,当鼠标划上去的时候会变色,让用户的体验非常好.为了满足用户需求,同时让代码效率 ...

  4. 使用MAP文件快速定位程序崩溃代码行

    作为程序员,平时最担心见到的事情就是程序发生了崩溃,无论是指针越界还是非法操作,都将给我们的应用系统 造成巨大的损失.但在一个大型系统的测试过程中,初期出现程序崩溃似乎成了不可避免的事.其实测试中出现 ...

  5. 使用MAP文件快速定位程序崩溃代码行(转)

    作为程序员,平时最担心见到的事情就是程序发生了崩溃,无论是指针越界还是非法操作,都将给我们的应用系统造成巨大的损失.但在一个大型系统的测试过程中,初期出现程序崩溃似乎成了不可避免的事.其实测试中出现程 ...

  6. oracle 小项目实战总结

    说明:钓鱼君昨天在网上找到一份oracle项目实战的文档,粗略看了一下大致内容,感觉自己很多知识不够扎实,便跟着文档敲了一遍,目前除了机械性代码没有实现外,主要涉及知识:创建表空间.创建用户.给用户赋 ...

  7. python一天学费多少_自学python一天的小项目实战

    最近想做一些自己的项目,需要网上采集一些数据,以前都是用火车头采集的,感觉很不灵活,于是今天就花了一些时间学下python 展示下今天的成果,做了两个小实战 一个是抖音去水印 另外一个是爬取B站上的视 ...

  8. 快速搭建后台框架D2admin项目实战(1)

    一.项目背景 最近要写个有关合同管理的业务系统 发现UI页面非常多,但是又大部分交互差不多,80%都是crud的.由此想到一个方案,封装一个可以配置表单和列表自动生成前端通用代码.有个朋友听到这种需求 ...

  9. Java开发快速学习!黑马java项目实战

    一面 自我介绍 项目中的监控:那个监控指标常见的有哪些? 微服务涉及到的技术以及需要注意的问题有哪些? 注册中心你了解了哪些? consul 的可靠性你了解吗? consul 的机制你有没有具体深入过 ...

  10. 小项目实战分享 | 用Python实现股票技术分析指标

    大家好,我是王某人. 股票是很多人感兴趣的,我用Python实现了股市技术分析中常见的指标,如:MA,MACD,RSI,BOLL,ATR,KDJ,CCI,PSY等,这些指标在通达信.同花顺等软件上都能 ...

最新文章

  1. YOLOv5添加注意力机制 Pytorch
  2. 求两个整数的最大公约数
  3. java.lang.illegalagr_spring – java.lang.IllegalArgumentException:环境不能为null
  4. antimalware可以关闭吗_EMUI这几个功能一定要关闭 不然手机会越来越卡
  5. 利用Linux命令和perl脚本批量将文件重命名
  6. elementui中给input框赋值成功后input框不能进行编辑问题
  7. Eclipse详细安装教程
  8. DirectX修复工具
  9. 超期天数计算机函数公式大全,Excel计算天数的函数与公式总结
  10. 第6节 蒙特卡罗模拟计算欧式期权价格
  11. verilog的描述风格
  12. 值得反复看的经典算法书
  13. 差之毫厘:etcd 3 完美支持 HTTP 访问
  14. win10硬盘锁怎么解除_如何取消硬盘锁?
  15. 2021年支付宝发大红包啦!人人有份,天天可领!领到直接当现金用!
  16. mosquitto使用的基本流程以及一些遇见的问题
  17. JQuery data方法的使用-遁地龙卷风
  18. 检查Office版本工具(通过注册表)
  19. 水位传感器(Water Sensor)原理图
  20. Python Tip挑战

热门文章

  1. 联想笔记本电脑开机无法修复计算机,联想笔记本开机没反应怎么办 笔记本无法开机的解决方法...
  2. 多拨软件测试,记一次折腾苏州移动宽带多拨的过程
  3. python一行输入多个值用空格隔开_Python 实现一行输入多个数字(用空格隔开)
  4. ios审核提示:您的 Apple Developer Program 帐户已被标记为删除
  5. elasticsearch(15) match_phase的使用 slop的使用
  6. 详解cmd修复系统命令操作方法
  7. python换行输入数据_python 对比两个文件内容或字符串内容时的换行符/交作业检测小程序...
  8. android金钱符号变形,使用¥(一个中文字宽)还是¥(半个中文字宽)?
  9. 如何免费拥有一个聊天机器人
  10. R语言计算回归模型R方(R-Squared)实战