这一系列的文章不是系统的介绍Lucene的, 只是在若干个点对Lucene的使用进行说明.需要系统的了解可以看
1) <<Lucene in Action>>
2) 车东写的Lucene教程
3) TJU某人写的如何加入分词
4) 3) 的相关代码
关于lucene用作站内搜索引擎的方案可以参见上面三个网站, 虽然它们是针对lucene2.3前的某些版本的, 代码中的接口函数可能跟lucene2.3有所不同(比如Field类), 但对lucene的介绍及一些代码会给你很大的帮助.
汉语的搜索离不开分词, 本想用ictclas+jni来做,结果找不到ictclas的源码, 在计算所也无从下载, 不过就在无助之时,看到有个ictclas4j, 用visio写的文档不错(算法框加应该是没问题的), 代码写得也很清楚(只是后来发现代码中的bug真是不少), 下来一试, 效果还不错, 词典那些以后都可以扩充.
这篇文章只讲对ictclas4j词典加载的改进,改后的加载速度是改前的五倍.
首先, 为什么词典加载慢, 读了源码后就会发现: 在读取词典文件的时候都是若干字节读取的, 这样浪费了IO的带宽,增加了IO的次数, 所以速度慢, 解决方法就是加Buffer, 以前没用过Java的读写文件buffer之类的功能,google了一下,发现JDK中就有现成的类: BufferedInputStream.下面是在Dictionary.java中增加的函数和在Dictionary.java中修改的函数
/**
* 修改的函数
*/
public
boolean
load(String filename)
{
// return load(filename, false);
return quickLoad(filename, false);
}

/**
* 新增的函数: 加速加载
*/
public
boolean
quickLoad(String filename,
boolean
isReset)
{
File file;

int[] nBuffer = new int[3];

file = new File(filename);
if (!file.canRead())
return false;// fail while opening the file

try {
delModified();

DataInputStream fis = new DataInputStream(new FileInputStream(file));
// 在写入文件之前加入一个buffer,大小为8192(=32*256)
BufferedInputStream in = new BufferedInputStream(fis);
for (int i = 0; i < Utility.CC_NUM; i++) {
// logger.debug("块" + i);
// 词典库在写二进制数据时采用低位优先(小头在前)方式,需要转换一下
int count = GFCommon.bytes2int(Utility.readBytes(in, 4), false);
// logger.debug(" count:" + count);
wts.get(i).setCount(count);
if (count <= 0)
continue;

WordItem[] wis = new WordItem[count];
for (int j = 0; j < count; j++) {
nBuffer[0] = GFCommon.bytes2int(Utility.readBytes(in, 4), false);
nBuffer[1] = GFCommon.bytes2int(Utility.readBytes(in, 4), false);
nBuffer[2] = GFCommon.bytes2int(Utility.readBytes(in, 4), false);

// String print = " wordLen:" + nBuffer[1] + " frequency:" +
// nBuffer[0] + " handle:" + nBuffer[2];

WordItem ti = new WordItem();
if (nBuffer[1] > 0)// String length is more than 0
{
byte[] word = Utility.readBytes(in, nBuffer[1]);
ti.setWord(new String(word, "GBK"));

} else
ti.setWord("");

// print += " word:(" + Utility.getGB(i) + ")" +
// ti.getWord();
// logger.debug(print);

if (isReset)// Reset the frequency
ti.setFreq(0);
else
ti.setFreq(nBuffer[0]);
ti.setLen(nBuffer[1] / 2);
ti.setHandle(nBuffer[2]);
wis[j] = ti;
}
wts.get(i).setWords(wis);
}

in.close();
} catch (FileNotFoundException e) {
logger.error(e);
} catch (IOException e) {
logger.error(e);
}
return true;
}
在Utility.java中加入以下函数:
public
static
byte
[] readBytes(BufferedInputStream in,
int
len)
{
if (in != null && len > 0) {
byte[] b = new byte[len];
try {
in.read(b, 0, len);
} catch (IOException e) {
e.printStackTrace();
}
return b;
}
return null;
}
就是这么简单, 另外 " 低位优先 "的方式, 应该可以变成高位优先, 这个我并没有修改.
这里讲加载词典, 之后会词做成的分词器出现的问题及解决方法.
1) <<Lucene in Action>>
2) 车东写的Lucene教程
3) TJU某人写的如何加入分词
4) 3) 的相关代码
关于lucene用作站内搜索引擎的方案可以参见上面三个网站, 虽然它们是针对lucene2.3前的某些版本的, 代码中的接口函数可能跟lucene2.3有所不同(比如Field类), 但对lucene的介绍及一些代码会给你很大的帮助.
汉语的搜索离不开分词, 本想用ictclas+jni来做,结果找不到ictclas的源码, 在计算所也无从下载, 不过就在无助之时,看到有个ictclas4j, 用visio写的文档不错(算法框加应该是没问题的), 代码写得也很清楚(只是后来发现代码中的bug真是不少), 下来一试, 效果还不错, 词典那些以后都可以扩充.
这篇文章只讲对ictclas4j词典加载的改进,改后的加载速度是改前的五倍.
首先, 为什么词典加载慢, 读了源码后就会发现: 在读取词典文件的时候都是若干字节读取的, 这样浪费了IO的带宽,增加了IO的次数, 所以速度慢, 解决方法就是加Buffer, 以前没用过Java的读写文件buffer之类的功能,google了一下,发现JDK中就有现成的类: BufferedInputStream.下面是在Dictionary.java中增加的函数和在Dictionary.java中修改的函数













































































在Utility.java中加入以下函数:












就是这么简单, 另外 " 低位优先 "的方式, 应该可以变成高位优先, 这个我并没有修改.
这里讲加载词典, 之后会词做成的分词器出现的问题及解决方法.