【转载保存】修改IK分词器源码实现动态加载词典
鏈接:http://www.gongstring.com/portal/article/index/id/59.html
當前IKAnalyzer從發布最后一個版本后就一直沒有再更新,使用過程中,經常遇到需要擴展詞庫以及動態更新字典表的問題,此處給出一種解決辦法(注意:本方法中的IKAnalyzer代碼我已經將源碼移植到了自己的工程中,目錄結構也進行了修改):
?
1、將擴展字典表做成可動態生成:
?1)、在IKAnalyzer.cfg.xml中添加擴展字典路徑
????
?2)、在分詞的時候,先采取動態生成上面兩個字典表的方式進行更新,例如事先將字典詞庫放在數據表中,需要分詞之前先更新字典。當然此方法只支持第一次調用的時候動態加載詞庫,如果服務沒有重啟之前,數據庫中添加的詞是不會進行重新加載的。下面是動態生成字典表的實現類:
package?com.chz.apps.sm.IKAnalyzer;import?java.io.ByteArrayInputStream; import?java.io.IOException; import?java.io.InputStream; import?java.io.InputStreamReader; import?java.io.Reader; import?java.util.ArrayList; import?java.util.List;import?com.chz.apps.sm.model.IkanalyzerExtendModel; import?com.chz.base.util.FileUtil; import?com.chz.plugin.IKAnalyzer.core.IKSegmenter; import?com.chz.plugin.IKAnalyzer.core.Lexeme;/***?@Description?分詞工具類*?@author?gongstring<1@gongstring.com>*?@createTime?2016年11月28日?下午2:46:06*/ public?class?IKAnalyzerTool?{/***?是否已經初始化過詞庫,如果沒有,則會自動先調用詞庫*/private?static?boolean?init_words?=?false;/***?擴展關鍵字*/private?static?List<String>?extendWords?=?new?ArrayList<String>();/***?停用關鍵字*/private?static?List<String>?stopWords?=?new?ArrayList<String>();/***?@Description?初始化詞庫以及停用詞*?@author?gongstring<1@gongstring.com>*?@createTime?2016年11月28日?下午2:29:59*/public?static?void?initWords(){//從關鍵字表中查詢擴展關鍵字,并生成到指定文件中IKAnalyzerTool.extendWords?=?new?ArrayList<String>();List<IkanalyzerExtendModel>?extendWords?=?IkanalyzerExtendModel.dao.findByProperty("status",?1);String?fileDirPath?=?IKAnalyzerTool.class.getResource("/com/chz/apps/sm/IKAnalyzer/").getPath();String?filePath?=?fileDirPath+"extend.dic";FileUtil.removeFile(filePath);//先刪除文件,此處重新生成for?(int?i?=?0;?i?<?extendWords.size();?i++)?{String?txt?=?extendWords.get(i).getStr("extend_word");FileUtil.appendToFile(filePath,?txt,true);IKAnalyzerTool.extendWords.add(txt);}//從關鍵字表中查詢停用關鍵字,并生成到指定文件中IKAnalyzerTool.stopWords?=?new?ArrayList<String>();List<IkanalyzerExtendModel>?stopWords?=?IkanalyzerExtendModel.dao.findByProperty("status",?0);String?stopFilePath?=?fileDirPath+"stopword.dic";FileUtil.removeFile(stopFilePath);//先刪除文件,此處重新生成for?(int?i?=?0;?i?<?stopWords.size();?i++)?{String?txt?=?stopWords.get(i).getStr("extend_word");FileUtil.appendToFile(stopFilePath,?txt,true);IKAnalyzerTool.stopWords.add(txt);}init_words?=?true;}/***?@Description?分詞操作*?@author?gongstring<1@gongstring.com>*?@createTime?2016年11月28日?下午3:30:10*?@param?str*?@param?justExist?是否只顯示已經在詞庫中維護了的關鍵詞*?@return*/public?static?List<String>?IKAnalysis(String?str,boolean?justExist)?{List<String>?tmp?=?IKAnalysis(str);List<String>?result?=?new?ArrayList<String>();if(justExist){for?(int?i?=?0;?i?<?tmp.size();?i++)?{if(IKAnalyzerTool.extendWords.contains(tmp.get(i))){result.add(tmp.get(i));}}}else{result?=?tmp;}return?result;}/***?@Description?根據字符串自動拆分成關鍵字集合*?@author?gongstring<1@gongstring.com>*?@createTime?2016年11月28日?下午2:55:24*?@param?str*?@return*/public?static?List<String>?IKAnalysis(String?str)?{if(!init_words){initWords();}List<String>?result?=?new?ArrayList<String>();try?{//?InputStream?in?=?new?FileInputStream(str);//byte[]?bt?=?str.getBytes();//?strInputStream?ip?=?new?ByteArrayInputStream(bt);Reader?read?=?new?InputStreamReader(ip);IKSegmenter?iks?=?new?IKSegmenter(read,?true);Lexeme?t;while?((t?=?iks.next())?!=?null)?{result.add(t.getLexemeText());}}?catch?(IOException?e)?{//?TODO?Auto-generated?catch?blocke.printStackTrace();}return?result;}}?
2、修改源碼,實現動態更新字典表。通過查看源碼IKAnalyzer.dic.Dictionary.java文件得出,字典對象是采取單例模式,也就是第一次加載后,后續不在重新加載,這樣即使字典表內容變化,緩存中的字典庫是不會變更的,所以需要修改源碼,可以手動更新單例對象的內容,此處我采取添加clear方法,在需要更新時候調用,將instance對象設置為null,下次調用字典的時候,程序就會自動加載了
/***?@Description?清空字典緩存,用于動態更新字典表*?@author?gongstring<1@gongstring.com>*?@createTime?2016年11月29日?上午9:56:15*/public?static?void?clear(){singleton?=?null;}?
?
源碼修改完后,可以選擇編譯重新打包,或者將jar包中的class文件刪除,java類在工程中按照源目錄存放。
3、手動調用,我這里是做的一個頁面,點擊更新字典庫時,調用更新代碼:
/***?@Description?刷新關鍵詞緩存*?@author?gongstring<1@gongstring.com>*?@createTime?2016年11月29日?上午9:33:49*/public?void?refreshCache(){IKAnalyzerTool.initWords();//重新加載詞匯Dictionary.clear();//將字典表緩存清空this.renderSuccessJson(EnvConfig.APP_PATH+"/sm/ikanalyzerExtend");}?
4、可能存在的性能問題:由于詞庫一般會比較大,所以每次大批量更新可能會出現性能損耗。。。
總結
以上是生活随笔為你收集整理的【转载保存】修改IK分词器源码实现动态加载词典的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【搜索引擎】lucene事务
- 下一篇: 步入github世界