首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

Lucene学习之Lucene入门暨中文文件搜索有关问题的解决

2013-10-31 
Lucene学习之Lucene入门暨中文文件搜索问题的解决Lucene是一款优秀的全文检索引擎的框架,提供了完整的查询

Lucene学习之Lucene入门暨中文文件搜索问题的解决

Lucene是一款优秀的全文检索引擎的框架,提供了完整的查询引擎和索引引擎。由于Lucene自带的例子可以正常处理英文文件,但是中文的文件却不能正常处理。网上查了很多资料,很多人都在问这个问题,但是答案却是只字片语,没有针对这个问题提出一个完整的解决办法。经过一番摸索,终于解决了这个问题。关键之处在于读入文件时需要为文件字符流指定编码字符集,并且该字符集需要与文件的编码字符集一致,才能保证根据这些文件创建的索引后,文件的内容能被正确搜索。目前Lucene已经更新到了4.5.1,本文既可以作为最新版本的入门例子,有可以为解决中文文件搜索提供参考。

?

在D:/work/lucene/example放入测试的文件

D:/work/lucene/index01 为索引文件的存放路径

?

代码如下(基于Lucene4.5.1编写):

package com.hsdl.lucene;import info.monitorenter.cpdetector.io.ASCIIDetector;import info.monitorenter.cpdetector.io.CodepageDetectorProxy;import info.monitorenter.cpdetector.io.JChardetFacade;import info.monitorenter.cpdetector.io.ParsingDetector;import info.monitorenter.cpdetector.io.UnicodeDetector;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.document.Field;import org.apache.lucene.document.StringField;import org.apache.lucene.document.TextField;import org.apache.lucene.index.CorruptIndexException;import org.apache.lucene.index.DirectoryReader;import org.apache.lucene.index.IndexReader;import org.apache.lucene.index.IndexWriter;import org.apache.lucene.index.IndexWriterConfig;import org.apache.lucene.index.IndexWriterConfig.OpenMode;import org.apache.lucene.queryparser.classic.ParseException;import org.apache.lucene.queryparser.classic.QueryParser;import org.apache.lucene.search.IndexSearcher;import org.apache.lucene.search.Query;import org.apache.lucene.search.ScoreDoc;import org.apache.lucene.search.TopDocs;import org.apache.lucene.store.Directory;import org.apache.lucene.store.FSDirectory;import org.apache.lucene.store.LockObtainFailedException;import org.apache.lucene.util.Version;public class LuceneDemo {private static String contentFieldName = "content";public static void main(String[] args) {Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_45);try {String docPath = "D:/work/lucene/example";String indexPath = "D:/work/lucene/index01";//创建索引createIndex(analyzer, indexPath, docPath);//搜索search(analyzer, indexPath, "中国");} catch (CorruptIndexException e) {e.printStackTrace();} catch (LockObtainFailedException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (ParseException e) {// TODO Auto-generated catch blocke.printStackTrace();} }/** * 创建索引 *  * @param analyzer * @param indexPath * @param docPath * @throws IOException * @throws CorruptIndexException * @throws LockObtainFailedException */private static void createIndex(Analyzer analyzer, String indexPath,String docPath) throws IOException, CorruptIndexException,LockObtainFailedException {IndexWriter iwriter;Directory directory = FSDirectory.open(new File(indexPath));// 配置IndexWriterConfigIndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_45,analyzer);iwConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);iwriter = new IndexWriter(directory, iwConfig);File file = new File(docPath);indexDocs(iwriter, file);iwriter.close();}/** * 搜索 *  * @param analyzer * @param indexPath * @param queryStr * @throws CorruptIndexException * @throws IOException * @throws ParseException */private static void search(Analyzer analyzer, String indexPath,String queryStr) throws CorruptIndexException, IOException,ParseException {Directory directory = FSDirectory.open(new File(indexPath));// 搜索过程**********************************// 实例化搜索器IndexReader ireader = DirectoryReader.open(directory);IndexSearcher isearcher = new IndexSearcher(ireader);// 使用QueryParser查询分析器构造Query对象QueryParser qp = new QueryParser(Version.LUCENE_45, contentFieldName, analyzer);qp.setDefaultOperator(QueryParser.AND_OPERATOR);Query query = qp.parse(queryStr);// 搜索相似度最高的5条记录TopDocs topDocs = isearcher.search(query, 5);System.out.println("命中:" + topDocs.totalHits);// 输出结果ScoreDoc[] scoreDocs = topDocs.scoreDocs;System.out.println(scoreDocs.length);for (int i = 0; i < scoreDocs.length; i++) {Document targetDoc = isearcher.doc(scoreDocs[i].doc);System.out.println("内容:" + targetDoc.toString());System.out.println(targetDoc.get("fileName") + "["+ targetDoc.get("path") + "]");}}/** * 根据指定存放内容的文件或目录创建索引 * @param iwriter * @param file * @throws IOException */public static void indexDocs(IndexWriter iwriter, File file) throws IOException {if (file.canRead())if (file.isDirectory()) {String[] files = file.list();if (files != null)for (int i = 0; i < files.length; i++)indexDocs(iwriter, new File(file, files[i]));} else {Document doc = null;FileInputStream fis=null;try {doc = new Document();doc.add(new StringField("ID", "10000", Field.Store.YES));fis = new FileInputStream(file);System.out.println(getFileCharset(file));doc.add(new TextField(contentFieldName, new BufferedReader(new InputStreamReader(fis, getFileCharset(file)))));doc.add(new StringField("fileName", file.getName(),Field.Store.YES));doc.add(new StringField("path", file.getAbsolutePath(),Field.Store.YES));iwriter.addDocument(doc);} finally {if(fis!=null){fis.close();}}}}/** * 获取文件的编码字符集 * @param file * @return */public static String getFileCharset(File file) {/* * detector是探测器,它把探测任务交给具体的探测实现类的实例完成。 * cpDetector内置了一些常用的探测实现类,这些探测实现类的实例可以通过add方法 加进来,如ParsingDetector、 * JChardetFacade、ASCIIDetector、UnicodeDetector。 * detector按照“谁最先返回非空的探测结果,就以该结果为准”的原则返回探测到的 * 字符集编码。使用需要用到三个第三方JAR包:antlr.jar、chardet.jar和cpdetector.jar * cpDetector是基于统计学原理的,不保证完全正确。 */CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();/* * ParsingDetector可用于检查HTML、XML等文件或字符流的编码,构造方法中的参数用于 * 指示是否显示探测过程的详细信息,为false不显示。 */detector.add(new ParsingDetector(false));// ASCIIDetector用于ASCII编码测定detector.add(ASCIIDetector.getInstance());// UnicodeDetector用于Unicode家族编码的测定detector.add(UnicodeDetector.getInstance());/* * JChardetFacade封装了由Mozilla组织提供的JChardet,它可以完成大多数文件的编码 * 测定。所以,一般有了这个探测器就可满足大多数项目的要求,如果你还不放心,可以 * 再多加几个探测器,比如上面的ASCIIDetector、UnicodeDetector等。需要把这个放在最后添加。 */detector.add(JChardetFacade.getInstance());java.nio.charset.Charset charset = null;try {charset = detector.detectCodepage(file.toURI().toURL());} catch (Exception ex) {ex.printStackTrace();}if (charset != null){/* * 如果编码是"windows-1252",将其设置为"GB2312",因为使用的环境为中国, * 一般的文档也是在中文的Windows的环境下创建 */if(charset.name().equals("windows-1252")){return "GB2312";}return charset.name();}elsereturn null;}}

???

在运行该例子时除了需要Lucene4.5相关的jar包外,还需要antlr.jar、cpdetector_1.0.8.jar这两个jar包,才能正常编译运行。

在编写这个例子的时候,参考了网上其他朋友的文章及代码,在此一并感谢!

热点排行