“基于关键字匹配的文本过滤系统”配置文件的设计和实现(C/C++源码)
本文原始链接:http://blog.csdn.net/liigo/archive/2009/10/29/4744700.aspx
作者:liigo, 2009/10/29
转载请注明出处:http://blog.csdn.net/liigo
假设有一个基于关键字匹配的文本过滤系统,或类似的系统,需要一个配置文件,用于设定欲过滤的关键字列表。该怎么设计这样一个配置文件呢?又该如何编码实现呢?此文将给出一个可行的方案。这是本人(liigo)重复发明轮子系列文章的新一篇。
因为是一个小型应用系统,我对配置文件提出的要求是:简单直观,易于实现,同时保持足够的灵活性和可扩展性。
我对配置文件的设计结果如下:
文件是纯文本的,以行为处理单位;
行与行的分隔符可以是\r\n的任意组合,即支持WIN/LINUX/UNIX/MAC等多种换行模式;
行首以 "text:" 或 "literal:" 为前缀的,后面可以跟一个关键字常量,也可以跟“以半角逗号分隔的”多个关键字常量;
行首以 "regex:" 为前缀的,后面可以跟一个正则表达式文本;
":" 或 "," 后面可以有任意多个空白字符,解析时可自动略过;
如果没有歧义,可以省略行首的 "text:" 或 "literal:"。
根据以上设计结果,下面是一个合法的配置文件内容示例:
配置文件内容很简单,没有很特殊的语法,规则也很直观。
下面我说一下编码解析此文件的思路。
首先把文件读入内存,在末尾添加'\0'确保是合法的C语言文本;然后从头到尾逐字符遍历该文本,遇到回车符或换行等则临时停下来,把这个字符改写为'\0',这样就得到了一行文本(变量line始终指向每一行的行首);继续向后遍历字符,略过连续的回车符或换行符,进入下一行;如此循环下去就依次得到了每一行的内容,可分别交给下面的函数专门处理;遍历到结尾,无论是否遇到回车或换行等,都要取得最后一行文本(如果非空的话)并处理之。
接下来,写另外一个函数,专门处理文件中的每一行:判断行首如果是 "regex:" 则把后面的文本视为正则表达式,记录下来;判断行首如果是 "text:" 或 "literal:" 或没有此类前缀,则视为文本常量处理之。在文本常量的情况下,又分为“逗号分隔”和“非逗号分隔”两种情况,后者可视为前者的特例,可以统一处理,方法与上面类似,逐字符历遍找到逗号,把逗号字符改写为'\0'就得到了一个关键字文本常量,记录之;如此循环下去。
解析完成之后的结果是,得到了两个数组,一个是关键字常量文本指针数组,一个是用于匹配关键字的正则表达式对象指针数组。将来做关键字过滤时,只需分别遍历这两个数组,逐一检查关键字匹配情况即可。如需进一步提高执行效率,可在过滤之前事先将关键字常量文本置入哈希表等快速查询容器中。
这种文本解析方法,避免了文本分隔,避免了子文本的复制以及相应的内存申请和释放。
下面给出完整的文本解析代码(C/C++):
以上代码也是今天刚刚完成的,经初步测试可用,但还没有进行完整而严格的单元测试,可能会有一些BUG或缺陷,还请各位及时斧正。代码中出现的 BufferedMem 类,由于不涉及核心的文本解析算法,就不额外提供代码了。另外,由于这是特定于某个应用系统的内部应用,在通用性上可能做的不够(例如我假定了正则表达式不会以空白字符开头、关键字不能是空文本等)。