`
yangwei0915
  • 浏览: 459453 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

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 block
			e.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));
		// 配置IndexWriterConfig
		IndexWriterConfig 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();
		}
			
		else
			return null;
	}
}

   

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

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

分享到:
评论

相关推荐

    lucene3.6.1文件关键字搜索代码(附加核心包)

    lucene3.6.1文件关键字搜索代码(附加核心包),就是一个入门级的JAVA全局文件夹搜索案例、对于初学lucene很有帮助。

    lucene入门指南

    lucene入门指南 汇集网络一些精华和自己的总结

    全文检索 lucene-5.2.1 入门Eclipse工程实例

    Eclipse工程文件,全文检索 lucene-5.2.1 入门Eclipse工程实例,福利放送,与lucene3结果比对

    lucene入门demo

    里面编写了法创建,搜索的基本方法 LuceneDemo 单个文件索引,创建查找 CopyFile 为多文件复制多些文件做准备 CreateIndexe 多文件创建索引;Searcher多文件搜索对应CreateIndexe

    C#,学习全文检索的最佳入门之原始代码(非 Lucene)

    学习全文检索的最佳入门之原始代码(非 Lucene)。全文检索系统的实现技术分为三个方面:关系型全文检索系统、层次型全文检索系统、面向对象的全文检索系统及自动标引技术。 针对全文数据系统的构建,提出全文检索...

    Lucene入门源码

    Lucene源码,创建索引,搜索指定路径的txt文件,遍历文本,打印搜索结果

    lucene入门数据库资料

    博客使用的sql文件...

    Lucene介绍的PPT

    Lucene API的介绍,适合入门的人学习.包括全文索引文件的基本结构.

    Lucene详细使用文档

    好不容易整理的,分享给大家。 里面有4个文件,详细说明了全文检索的初步使用过程 ...第二个:lucene_初级学习资料.ppt 第三个:lucene_入门整理.pdf 第四个:Lucene教程详解.doc 绝对超值,新手必备宝典。超值分享。

    面向对象的全文搜索引擎hibernate-search入门例子

    hibernate-search小例子,myeclipse工程文件,有jar包,只要有mysql和myeclipse就可以直接运行。文章在http://blog.csdn.net/hortond。对文件索引和数据库感兴趣的可以下来看看,lucene是个很强大的全文搜索引擎。

    淘特站内搜索引擎(C#版)

    淘特站内搜索引擎是由淘特JSP搜索引擎发展而来,系统基于Lucene.Net核心,通过高效的中文分词算法将数据库中内容进行分析、索引并保存至硬盘中。前台搜索时,通过读取索引文件查询,避免了传统数据库查询在高并发及...

    Nutch入门.rar

    Nutch入门学习 7.1 概述...41 7.2 MapReduce.......41 7.3 文件系统语法......42 7.4 文件系统设计......42 7.5 系统的可用性......43 7.6 Nutch文件系统工作架构...43 8. nutch应用.45 8.1 修改源码.....45...

    大数据基础知识入门.pdf

    大数据基础知识入门 社会保障事业部 张火磊 主要内容 大数据价值 03 大数据概念、特性、由来 01 大数据应用举例 04 02 Hadoop技术介绍 大数据概念、特性、由来 什么叫大数据? 麦肯锡全球研究所给出的定义是:一 种...

    Nutch相关框架视频教程 讲义 杨尚川

    1、 通过nutch,诞生了hadoop、tika、gora。 2、 nutch通过ivy来进行依赖管理(1.2之后)。 3、 nutch是使用svn进行源代码管理的。 4、 lucene、nutch、hadoop,在搜索界相当...7、 nutch入门重点在于分析nutch脚本文件

    Liferay入门帮助文档(Liferay开发指南)

    Liferay 是一个完整的门户解决方案,基于J2EE的应用,使用了EJB以及JMS等技术,前台界面部分使用Struts MVC 框架,基于XML的portlet配置文件可以自由地动态扩展,使用了Web服务来支持一些远程信息的获取,使用 ...

    Twitter爬网和搜索

    演示图片搜索首页 搜索结果入门先决条件创建一个Oracle帐户并下载 下载下载有用的资源: : 正在安装使用maven打开Java文件(导入pom.xml文件)。 对于React前端,下载已保存的依赖项npm init履带式使用更新 。 运行...

    Hadoop源码的入门解析

    Hadoop原来是Apache Lucene下的一个子项目,它最初是从Nutch项目中分离出来的专门负责分布式存储以及分布式运算的项目。简单地说来,Hadoop是一个可以更容易开发和运行处理大规模数据的软件平台。下面列举hadoop主要...

    elasticsearch-7.2.1:elasticsearch 7.2.1源码阅读

    弹性搜索分布式RESTful搜索引擎 ... 建立在Lucene之上每个分片都是功能齐全的Lucene索引Lucene的所有功能都可以通过简单的配置/插件轻松展现。 每次操作的一致性单文档级操作是原子的,一致的,隔离的和持久的。入门

    nutch 初学文档教材

    Nutch入门学习 7.1 概述...41 7.2 MapReduce.......41 7.3 文件系统语法......42 7.4 文件系统设计......42 7.5 系统的可用性......43 7.6 Nutch文件系统工作架构...43 8. nutch应用.45 8.1 修改源码.....45 8.2 ...

Global site tag (gtag.js) - Google Analytics