索引文件:[D:\luceneDemo\data\TXT小说\陛下是妻迷.txt] 大小:[1185.0 KB]
索引文件:[D:\luceneDemo\data\TXT小说\随身空间重生在七十年代.txt] 大小:[2245.0 KB]
索引文件:[D:\luceneDemo\data\TXT小说\韶光慢.txt] 大小:[3732.0 KB]
索引文件:[D:\luceneDemo\data\TXT小说\鬼知道鲛人是什么[娱乐圈].txt] 大小:[1870.0 KB]
索引文件:[D:\luceneDemo\data\农门娇妻:将军要耕田.txt] 大小:[3484.0 KB]
索引文件:[D:\luceneDemo\data\新建文本文档.txt] 大小:[0.0 KB]
===================================================
索引完毕:索引了[57]个文件、花费了 42376 毫秒
===================================================
开始搜索关键词:[佳佳] 发现了[11]个匹配文档
===================================================
D:\luceneDemo\data\新建文本文档.txt 大小:[0.0 KB]
D:\luceneDemo\data\test1008.docx 大小:[11.0 KB]
D:\luceneDemo\data\test1665.docx 大小:[11.0 KB]
D:\luceneDemo\data\TXT小说\他很撩很宠.txt 大小:[526.0 KB]
D:\luceneDemo\data\TXT小说\四神集团①:首席总裁的逃妻.txt 大小:[3167.0 KB]
D:\luceneDemo\data\TXT小说\第一宠婚:老公,坏坏坏!.txt 大小:[1357.0 KB]
D:\luceneDemo\data\TXT小说\六零小娇妻.txt 大小:[6316.0 KB]
D:\luceneDemo\data\TXT小说\豪门隐婚.txt 大小:[3345.0 KB]
D:\luceneDemo\data\TXT小说\侯门闺娇.txt 大小:[1002.0 KB]
D:\luceneDemo\data\TXT小说\鬼知道鲛人是什么[娱乐圈].txt 大小:[1870.0 KB]
D:\luceneDemo\data\TXT小说\豪门重生之娇妻养成.txt 大小:[4306.0 KB]
===================================================
 import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
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.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.poi.EmptyFileException;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.POIXMLTextExtractor;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.xmlbeans.XmlException;
import org.wltea.analyzer.lucene.IKAnalyzer; public class Retrieval { IndexWriter writer = null;
Directory dir = null;
Analyzer analyzer = null;
IndexWriterConfig config = null; // 文件目录
// 查询字符串
public List<String> RunRetrieval(String fileDir, String querystr) { // 添加到ext.dic
// appendMethodB(EXT_DIC_PATH,querystr); // 搜索结果
List<String> resFile = new ArrayList<String>(); String uuid = UUID.randomUUID().toString();
// 索引目录
String indexDir = fileDir + "\\..\\temp_" + uuid;
try {
long start = System.currentTimeMillis(); // 智能中文分析器
analyzer = new IKAnalyzer();
// 中文分词器
// analyzer=new SmartChineseAnalyzer();
// 实例化分析器
// analyzer = new StandardAnalyzer(); // 实例化IndexWriterConfig
config = new IndexWriterConfig(analyzer);
// 得到索引所在目录的路径
dir = FSDirectory.open(Paths.get(indexDir));
// 实例化IndexWriter
writer = new IndexWriter(dir, config);
// 定义文件数组,循环得出要加索引的文件
File[] files = new File(fileDir).listFiles();
if (null == files) {
System.out.println("没有文件");
return null;
}
for (File file : files) {
recursionDir(file);
} writer.commit(); // 返回索引了多少个文件,有几个文件返回几个
long end = System.currentTimeMillis();
System.out.println("===================================================");
System.out.println("索引完毕:索引了[" + writer.numDocs() + "]个文件、花费了 " + (end - start) + " 毫秒");
System.out.println("==================================================="); int hitsPerPage = 100; IndexReader reader = DirectoryReader.open(dir);
IndexSearcher searcher = new IndexSearcher(reader);
Term term = new Term("contents", querystr);
// Query q = new QueryParser("contents", analyzer).parse(querystr);
TermQuery query = new TermQuery(term); TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage);
System.out.print("开始搜索关键词:[" + querystr + "] ");
searcher.search(query, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs; System.out.println("发现了[" + hits.length + "]个匹配文档");
System.out.println("===================================================");
for (int i = 0; i < hits.length; ++i) {
int docId = hits[i].doc;
Document doc = searcher.doc(docId); // System.out.println(doc.get("contents"));
// System.out.print(doc.get("FileName"));
System.out.print(doc.get("fullPath") + " 大小:[" + doc.get("size") + " KB]");
resFile.add(doc.get("fullPath")); // displayTokens(analyzer, txt2String(new File(doc.get("fullPath"))), querystr);
System.out.println();
// System.out.print(" "+doc.get("size"));
}
reader.close();
System.out.println("===================================================");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != writer) {
// 删除索引
writer.deleteAll();
writer.close();
// 删除索引文件(不是程序运行所必须的)
deleteDir(new File(indexDir));
}
} catch (IOException e) {
e.printStackTrace();
}
}
return resFile;
} private void writeToIndex(File file) { WordExtractor extractorForDoc = null;
POIXMLTextExtractor extractorForDocx = null; try { if (file.length() == 0) {
return;
} double fileLength = file.length() / 1000; // 从这开始,对每个文件加索引
System.out.println("索引文件:[" + file.getCanonicalPath() + "] 大小:[" + fileLength + " KB]");
// 索引要一行一行的找,,在数据中为文档,所以要得到所有行,即文档
// 实例化Document
Document document = new Document();
String prefix = file.getName().substring(file.getName().lastIndexOf(".") + 1); // 如果是Word
if (prefix.equals("docx")) {
extractorForDocx = new XWPFWordExtractor(POIXMLDocument.openPackage(file.getAbsolutePath()));
Reader contents = new StringReader(extractorForDocx.getText());
// add():把设置好的索引加到Document里,以便在确定被索引文档。
document.add(new TextField("contents", contents));
} else if (prefix.equals("doc")) {
FileInputStream inputStream = new FileInputStream(file.getAbsolutePath());
extractorForDoc = new WordExtractor(inputStream);
Reader contents = new StringReader(extractorForDoc.getText());
// add():把设置好的索引加到Document里,以便在确定被索引文档。
document.add(new TextField("contents", contents));
} else if (prefix.equals("txt")) {
// add():把设置好的索引加到Document里,以便在确定被索引文档。
document.add(new TextField("contents", new FileReader(file)));
}
// Field.Store.YES:把文件名存索引文件里,为NO就说明不需要加到索引文件里去
document.add(new StringField("FileName", file.getName(), Field.Store.YES));
// 把完整路径存在索引文件里
document.add(new StringField("fullPath", file.getCanonicalPath(), Field.Store.YES)); // document.add(new TextField("size", file.getTotalSpace() + " bytes",
// Field.Store.YES));
document.add(new TextField("size", String.valueOf(fileLength), Field.Store.YES)); // 开始写入,就把文档写进了索引文件里去了;
writer.addDocument(document); } catch (EmptyFileException e) { } catch (IOException e) {
e.printStackTrace();
} catch (XmlException e) {
e.printStackTrace();
} catch (OpenXML4JException e) {
e.printStackTrace();
} finally {
try {
if (null != extractorForDoc) {
extractorForDoc.close();
}
if (null != extractorForDocx) {
extractorForDocx.close();
}
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
} @SuppressWarnings("unused")
private void recursionDir(File f) {
if (f != null) {
if (f.isDirectory()) {
File[] fileArray = f.listFiles();
if (fileArray != null) {
for (int i = 0; i < fileArray.length; i++) {
// 递归调用
recursionDir(fileArray[i]);
}
}
} else {
writeToIndex(f);
}
}
} private void displayTokens(Analyzer analyzer, String text, String keyword) throws Exception { // System.out.println("当前使用的分词器:" + analyzer.getClass().getName()); // 分词流,即将对象分词后所得的Token在内存中以流的方式存在,也说是说如果在取得Token必须从TokenStream中获取,而分词对象可以是文档文本,也可以是查询文本。
TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(text));
// 表示token的首字母和尾字母在原文本中的位置。比如I'm的位置信息就是(0,3),需要注意的是startOffset与endOffset的差值并不一定就是termText.length(),
// 因为可能term已经用stemmer或者其他过滤器处理过;
OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
// 这个有点特殊,它表示tokenStream中的当前token与前一个token在实际的原文本中相隔的词语数量,用于短语查询。比如:
// 在tokenStream中[2:a]的前一个token是[1:I'm ],
// 它们在原文本中相隔的词语数是1,则token="a"的PositionIncrementAttribute值为1;
PositionIncrementAttribute positionIncrementAttribute = tokenStream
.addAttribute(PositionIncrementAttribute.class); CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class); // 表示token词典类别信息,默认为“Word”,比如I'm就属于<APOSTROPHE>,有撇号的类型;
TypeAttribute typeAttribute = tokenStream.addAttribute(TypeAttribute.class);
tokenStream.reset(); int position = 0;
while (tokenStream.incrementToken()) {
int increment = positionIncrementAttribute.getPositionIncrement();
if (increment > 0) {
position = position + increment;
}
int startOffset = offsetAttribute.startOffset();
int endOffset = offsetAttribute.endOffset();
String term = charTermAttribute.toString();
// System.out.println("第" + position + "个分词:TYPE:" + typeAttribute.type() + "、["
// + term + "]" + "、位置:["
// + startOffset + "-->" + endOffset + "]");
if (term.equals(keyword)) {
System.out.println("第" + position + "个分词:TYPE:" + typeAttribute.type() + "、[" + term + "]" + "、位置:["
+ startOffset + "-->" + endOffset + "]");
}
}
tokenStream.close();
} /**
* 读取txt文件的内容
*
* @param file
* 想要读取的文件对象
* @return 返回文件内容
*/
public static String txt2String(File file) {
StringBuilder result = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(file));// 构造一个BufferedReader类来读取文件
String s = null;
while ((s = br.readLine()) != null) {// 使用readLine方法,一次读一行
result.append(System.lineSeparator() + s);
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return result.toString();
} /**
* 递归删除目录下的所有文件及子目录下所有文件
*
* @param dir
* 将要删除的文件目录
*
*/
private static boolean deleteDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// 目录此时为空,可以删除
return dir.delete();
} /**
* B方法追加文件:使用FileWriter
*/
public static void appendMethodB(String fileName, String content) {
try {
// 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
FileWriter writer = new FileWriter(fileName, true);
// FileWriter writer = new FileWriter(fileName, false);
writer.write("\r\n");
// content=new String(content.getBytes("ISO-8859-1"),"UTF-8");
System.out.println("写入新词汇到ext.dic:[" + content + "]");
writer.write(content);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

全文检索 java Lucene的更多相关文章

  1. JAVAEE——Lucene基础:什么是全文检索、Lucene实现全文检索的流程、配置开发环境、索引库创建与管理

    1. 学习计划 第一天:Lucene的基础知识 1.案例分析:什么是全文检索,如何实现全文检索 2.Lucene实现全文检索的流程 a) 创建索引 b) 查询索引 3.配置开发环境 4.创建索引库 5 ...

  2. 全文检索框架---Lucene

    一.什么是全文检索 1.数据分类 我们生活中的数据总体分为两种:结构化数据和非结构化数据.   结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等.   非结构化数据:指不定长或无固定格式 ...

  3. 全文检索(Lucene&Solr)

    全文检索(Lucene&Solr) 1)什么是全文检索?为什么需要全文检索? 结构化数据(mysql等)方便查询,而非结构化数据(如多篇文章)是难以查询到自己需要的,所以要使用全文检索. 全文 ...

  4. 【手把手教你全文检索】Lucene索引的【增、删、改、查】

    前言 搞检索的,应该多少都会了解Lucene一些,它开源而且简单上手,官方API足够编写些小DEMO.并且根据倒排索引,实现快速检索.本文就简单的实现增量添加索引,删除索引,通过关键字查询,以及更新索 ...

  5. Lucene 01 - 初步认识全文检索和Lucene

    目录 1 搜索简介 1.1 搜索实现方案 1.2 数据查询方法 1.2.1 顺序扫描法 1.2.2 倒排索引法(反向索引) 1.3 搜索技术应用场景 2 Lucene简介 2.1 Lucene是什么 ...

  6. 大型运输行业实战_day15_1_全文检索之Lucene

    1.引入 全文检索简介: 非结构化数据又一种叫法叫全文数据.从全文数据(文本)中进行检索就叫全文检索. 2.数据库搜索的弊端 案例 :     select  *  from product  whe ...

  7. 全文检索技术---Lucene

    1       Lucene介绍 1.1   什么是Lucene Lucene是apache下的一个开源的全文检索引擎工具包.它为软件开发人员提供一个简单易用的工具包(类库),以方便的在目标系统中实现 ...

  8. 全文检索以及Lucene的应用

    全文检索 一.什么是全文检索? 就是在检索数据,数据的分类: 在计算机当中,比如说存在磁盘的文本文档,HTML页面,Word文档等等...... 1.结构化数据 格式固定,长度固定,数据类型固定等等, ...

  9. Java Lucene入门

    1.lucene版本:7.2.1 pom文件: <?xml version="1.0" encoding="UTF-8"?> <project ...

随机推荐

  1. ucore os 前初始化

    BIOS 初始化完成说起 连接的时候指定了 -Ttext 0x7c00 也指定了 -e start 所以booasm.S 中的start 就呗钦定为程序入口了. 开始就是 屏蔽中断 初始化段寄存器 使 ...

  2. Angular.js的自定义功能

    1,自定义指令,在html中输入标签显示想要的指令 html script部分 2,标签中的属性的 有属性值时可以通过函数的参数返回属性值 没有属性值时可以设置属性值(自定义属性值) html部分   ...

  3. 2017-09-23-ArchData

    layout: post title: ArchData category: Technical tags: [分布式,区块链,AI,大数据] ArchData 技术峰会 神经网络和函数式编程 杨博: ...

  4. python利用Remove.bg接口自动去背景(转)

    转 https://blog.csdn.net/Quentin_he/article/details/97569625 前段时间基友找我让帮忙把他的结婚登记照扣出来换一个背景当作简历照,好在我之前学过 ...

  5. javascript之键盘事件的方法

    键盘事件包含onkeydown.onkeypress和onkeyup这三个事件 事件初始化 function keyDown(){} document.onkeydown = keyDown; //论 ...

  6. R语言可视化--qplot函数

    ggplot绘图系统 使用动词名词形容词构造句子的过程,将数据映射到美学属性上的过程,由层组成 绘图函数 qplot() :参数包括美学属性.几何体.面.统计.坐标系.主题这些层次. ggplot() ...

  7. hihocoder1317 :搜索四·跳舞链

    精确覆盖问题是指对于给定的一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1. //Achen #include<algorithm> #include< ...

  8. HR招聘_(三)_招聘方法论(招聘途径及流程)

    1.招聘途径 网络招聘:企业官网,招聘网站,微信,论坛等. 校园招聘:学校信息栏海报,学校组织招聘会,校企业联合专场. 现场招聘会: 专场招聘会,人才市场招聘会. 猎头公司:猎头(年薪高于350K), ...

  9. Java开发中的Memcache原理及实现

    Memcached 客户端程序 Memcached的java客户端已经存在三种了: ?  官方提供的基于传统阻塞io由Greg Whalin维护的客户端 ?  Dustin Sallings实现的基于 ...

  10. HTML之meta标签缓存控制

    <meta http-equiv="pragram" content="no-cache"> 禁止浏览器从本地缓存中调阅页面. 网页不保存在缓存中, ...