Java的lucene是正统,功能更强大,开发快速,而且和J2EE天然融合(都是使用Java),怎么看都比clucene强多了。那为什么要使用clucene呢?原因有两个:
一:C++的速度快。当对索引速度有更高数量级的要求时,单纯设置MergeFactor和MinMergeDocNum无法实现的。
二:索引的内容如果是另外的C++写的工具的结果,那么用clucene就比lucene有优势,否则要么使用文件作为中间结果,要么使用JNI,都不是很好的办法。综上,clucene还是有点用的。
《lucene in action》中在介绍clucene是居然没有提clucene的索引与lucene的兼容性,倒是对C#的Dotlucene大书特书。实际上,clucene的索引目前来说还是和lucene兼容的。clucene的作者mail list里提到好像要放弃这种兼容性,天晓得以后会怎样。反正现在是兼容的。
默认情况下(configure的时候带参数--enable-ucs2 即使用ucs2编码),clucene使用的是wchar_t类型。这个wchar_t在windows下为2个字节,在linux下为4个字节,不过无所谓,对于clucene来说没有什么影响。
Java在读入文本时,可以指定编码。如果没有指定,则使用系统默认的编码。windows(中文版)为ansi,实际上就是GBK。linux系统默认 的编码似乎和locale有关,一般情况下为utf-8。将文本读入内存后,Java统一使用unicode对字符编码,所以只要读入时的编码正确,就没 有问题。Java版的lucene写索引时使用modified utf-8编码,与utf-8的区别在于对'\0'进行处理,把它写成两个字节。另外modified utf-8编码最长使用3字节。
可惜clucene没有Java那么多库可以用。为了省事,它才不管原始文件是GBK、BIG5还是UTF-8编码,完全按照UNICODE处理。这种情 况下,如果程序没有崩溃(奇迹...),生成的索引对于Java版的lucene来说完全是天书。当然,ASCII码除外。
为了解决这个问题,可以在进行索引之前,把文本转化为unicode。linux下有著名的iconv包。听说windows下有专门的api。这里需要注意的是,用iconv生成的unicode是小尾端(little endian),所以转化后读入wchar_t时要
char* result;
iconv(...,&result,...);
......
//result中保存转换好的unicode字符
size_t s = strlen(result);
size_t i = 0;
char high, low;
while(i<s){
low = result[i];
high = result[i+1];
wchar_t w = (low & 0xff) + ((high & 0xff)<<8);
i += 2;
}
......
这样子才能正确解析。
如此一来,clucene生成的索引就可以被lucene识别了。前台还是使用J2EE,管它什么Struts,还是Servlet,后台生成索引部分就 完全用clucene来替代。经过实验对比,在数据量不大的情况下,clucene建索引的速度是lucene的两倍左右。
之所以提高不明显,因为创建索引时的io太多。对于io来说C++相对与Java确实优势不大。但是待索引的内容是其他C++工具生成的,比如SVM,CRF,LDA等等,这些工具的C++版肯定是比Java版要快得多,所以改用clucene还是值得的。