1.基于分布式系统的自定义分词要求与流程设计
(见图)E:\plan\readingnote\分词与索引\分词\2012-4-20
2.分词实现原理——词典的加载过程
2.1.分词词典的加载过程涉及到3个类,分别是Configuration类,Directory类,以及DictSegment类。
其中前两个类是获得配置文件,获得分词词典的,为词典内容的加载做准备的。而DictSegment类则是实现真正的分词加载的类。
2.2.在调用分词的过程中,首先调用Directory类对象,在方法loadMainDict()中,包含了自定义分词词典内容的加载。
2.2.1.在自定义分词内容的加载中,首先调用Configuration类中的一个方法,用来获得IKAnalyzer.cfg.xml(自定义词典文件配置路径)中配置的自定义词典文件的配置路径。List extDictFiles = Configuration.getExtDictionarys();在这之前,得先获得配置文件的路径,并将其作为流加载到内存中。其实,这两件事情都是在Configuration类中实现的,Directory类只是调用了Configuration类提供的接口而已。
2.2.2.现在来看看Configuration类中做的两件事。
private Configuration(){
props = new Properties();
//
String path=Configuration.class.getResource(FILE_NAME).toString();
//
String path2=Configuration.class.getResource("").toString();
//
String path3=Configuration.class.getResource("/").toString();
InputStream input = Configuration.class.getResourceAsStream(FILE_NAME);
if(input != null){
try {
props.loadFromXML(input);
} catch (InvalidPropertiesFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(1)初始化。将IKAnalyzer.cfg.xml作为流加载到内存中。注意加粗的代码,这就使得在不修改代码的情况下,只能加载到类所在的classpath路径下的文件。(对于加粗代码的理解,详见E:\plan\readingnote\分词与索引\分词\分词自定义词典路径
)
public static List getExtDictionarys(){
List extDictFiles = new ArrayList(2);
String extDictCfg = CFG.props.getProperty(EXT_DICT);
if(extDictCfg != null){
//使用;分割多个扩展字典配置
String[] filePaths = extDictCfg.split(";");
if(filePaths != null){
for(String filePath : filePaths){
if(filePath != null && !"".equals(filePath.trim())){
extDictFiles.add(filePath.trim());
//System.out.println(filePath.trim());
}
}
}
}
return extDictFiles;
}
(2)该段代码用来实现从IKAnalyzer.cfg.xml中获取自定义词典配置路径,并将其放入一个集合中,作为返回值返回。
2.2.3现在转回到Directory类。在获得自定义词典文件路径之后,就是根据文件路径找到自定义词典,然后调用DircSegment加载到内村中。
List extDictFiles = Configuration.getExtDictionarys();
if(extDictFiles != null){
for(String extDictName : extDictFiles){
//读取扩展词典文件
is = Dictionary.class.getResourceAsStream(extDictName);
//如果找不到扩展的字典,则忽略
if(is == null){
continue;
}
try {
BufferedReader br = new BufferedReader(new InputStreamReader(is , "UTF-8"), 512);
String theWord = null;
do {
theWord = br.readLine();
if (theWord != null && !"".equals(theWord.trim())) {
//加载扩展词典数据到主内存词典中
//System.out.println(theWord);
_MainDict.fillSegment(theWord.trim().toCharArray());
}
} while (theWord != null);
} catch (IOException ioe) {
System.err.println("Extension Dictionary loading exception.");
ioe.printStackTrace();
}finally{
try {
if(is != null){
is.close();
is = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
注意到粗体部分,这就要求其只能获得Directory类所在的classpath路径下的资定义词典文件,超出了这个路径范围这找不到了。第二个粗体部分则是调用DictSegment对自定义词典中的词进行加载。