转载请注明出处:http://blog.csdn.net/dongdong9223/article/details/76273859

本文出自【我是干勾鱼的博客

这里讲一下使用Lucene对doc、docx、pdf、txt文档进行全文检索功能的实现。

涉及到的类一共有两个:

LuceneCreateIndex,创建索引:

package com.yhd.test.poi;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.util.PDFTextStripper;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

public class LuceneCreateIndex {

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        // 保存word文件的路径
        String dataDirectory = "D:\\Studying\\poi\\test\\dataDirectory";
        // 保存Lucene索引文件的路径
        String indexDirectory = "D:\\Studying\\poi\\test\\indexDirectory";
        // 创建Directory对象 ,也就是分词器对象
        Directory directory = new SimpleFSDirectory(new File(indexDirectory));
        // 创建一个简单的分词器,可以对数据进行分词
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);

        // 创建索引实例
        // 第1个参数是Directory,
        // 第2个是分词器,
        // 第3个表示是否是创建, true代表覆盖原先数据, 如果为false为在此基础上面修改,
        // 第4个MaxFieldLength表示对每个Field限制建立分词索引的最大数目,
        // 如果是MaxFieldLength.UNLIMITED,表示长度没有限制;
        // 如果是MaxFieldLength.LIMITED则表示有限制,可以通过IndexWriter对象的setMaxFieldLength(int
        // n)进行指定
        IndexWriter indexWriter = new IndexWriter(directory, analyzer, true,
                IndexWriter.MaxFieldLength.UNLIMITED);
        // 获取所有需要建立索引的文件
        File[] files = new File(dataDirectory).listFiles();

        for (int i = 0; i < files.length; i++) {
            // 文件是第几个
            System.out.println("这是第" + i + "个文件----------------");
            // 文件的完整路径
            System.out.println("完整路径:" + files[i].toString());
            // 获取文件名称
            String fileName = files[i].getName();
            // 获取文件后缀名,将其作为文件类型
            String fileType = fileName.substring(fileName.lastIndexOf(".") + 1,
                    fileName.length()).toLowerCase();
            // 文件名称
            System.out.println("文件名称:" + fileName);
            // 文件类型
            System.out.println("文件类型:" + fileType);

            Document doc = new Document();

            // String fileCode = FileType.getFileType(files[i].toString());
            // 查看各个文件的文件头标记的类型
            // System.out.println("fileCode=" + fileCode);

            InputStream in = new FileInputStream(files[i]);
            InputStreamReader reader = null;

            if (fileType != null && !fileType.equals("")) {

                if (fileType.equals("doc")) {
                    // 获取doc的word文档
                    WordExtractor wordExtractor = new WordExtractor(in);
                    // 创建Field对象,并放入doc对象中
                    // Field的各个字段含义如下:
                    // 第1个参数是设置field的name,
                    // 第2个参数是value,value值可以是文本(String类型,Reader类型或者是预分享的TokenStream),
                    // 二进制(byet[]), 或者是数字(一个 Number类型)
                    // 第3个参数是Field.Store,选择是否存储,如果存储的话在检索的时候可以返回值
                    // 第4个参数是Field.Index,用来设置索引方式
                    doc.add(new Field("contents", wordExtractor.getText(),
                            Field.Store.YES, Field.Index.ANALYZED));
                    // 关闭文档
                    wordExtractor.close();
                    System.out.println("注意:已为文件“" + fileName + "”创建了索引");

                } else if (fileType.equals("docx")) {
                    // 获取docx的word文档
                    XWPFWordExtractor xwpfWordExtractor = new XWPFWordExtractor(
                            new XWPFDocument(in));
                    // 创建Field对象,并放入doc对象中
                    doc.add(new Field("contents", xwpfWordExtractor.getText(),
                            Field.Store.YES, Field.Index.ANALYZED));
                    // 关闭文档
                    xwpfWordExtractor.close();
                    System.out.println("注意:已为文件“" + fileName + "”创建了索引");

                } else if (fileType.equals("pdf")) {
                    // 获取pdf文档
                    PDFParser parser = new PDFParser(in);
                    parser.parse();
                    PDDocument pdDocument = parser.getPDDocument();
                    PDFTextStripper stripper = new PDFTextStripper();
                    // 创建Field对象,并放入doc对象中
                    doc.add(new Field("contents", stripper.getText(pdDocument),
                            Field.Store.NO, Field.Index.ANALYZED));
                    // 关闭文档
                    pdDocument.close();
                    System.out.println("注意:已为文件“" + fileName + "”创建了索引");

                } else if (fileType.equals("txt")) {
                    // 建立一个输入流对象reader
                    reader = new InputStreamReader(in);
                    // 建立一个对象,它把文件内容转成计算机能读懂的语言
                    BufferedReader br = new BufferedReader(reader);
                    String txtFile = "";
                    String line = null;

                    while ((line = br.readLine()) != null) {
                        // 一次读入一行数据
                        txtFile += line;
                    }
                    // 创建Field对象,并放入doc对象中
                    doc.add(new Field("contents", txtFile, Field.Store.NO,
                            Field.Index.ANALYZED));
                    System.out.println("注意:已为文件“" + fileName + "”创建了索引");

                } else {

                    System.out.println();
                    continue;

                }

            }
            // 创建文件名的域,并放入doc对象中
            doc.add(new Field("filename", files[i].getName(), Field.Store.YES,
                    Field.Index.NOT_ANALYZED));
            // 创建时间的域,并放入doc对象中
            doc.add(new Field("indexDate", DateTools.dateToString(new Date(),
                    DateTools.Resolution.DAY), Field.Store.YES,
                    Field.Index.NOT_ANALYZED));
            // 写入IndexWriter
            indexWriter.addDocument(doc);
            // 换行
            System.out.println();
        }
        // 查看IndexWriter里面有多少个索引
        System.out.println("numDocs=" + indexWriter.numDocs());
        // 关闭索引
        indexWriter.close();

    }
}

LuceneSearch,进行搜索:

package com.yhd.test.poi;

import java.io.File;
import java.io.IOException;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.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.SimpleFSDirectory;
import org.apache.lucene.util.Version;

public class LuceneSearch {
    public static void main(String[] args) throws IOException, ParseException {
        // 保存索引文件的地方
        String indexDirectory = "D:\\Studying\\poi\\test\\indexDirectory";
        // 创建Directory对象 ,也就是分词器对象
        Directory directory = new SimpleFSDirectory(new File(indexDirectory));
        // 创建 IndexSearcher对象,相比IndexWriter对象,这个参数就要提供一个索引的目录就行了
        IndexSearcher indexSearch = new IndexSearcher(directory);
        // 创建QueryParser对象,
        // 第1个参数表示Lucene的版本,
        // 第2个表示搜索Field的字段,
        // 第3个表示搜索使用分词器
        QueryParser queryParser = new QueryParser(Version.LUCENE_30,
                "contents", new StandardAnalyzer(Version.LUCENE_30));
        // 生成Query对象
        Query query = queryParser.parse("百度");
        // 搜索结果 TopDocs里面有scoreDocs[]数组,里面保存着索引值
        TopDocs hits = indexSearch.search(query, 10);
        // hits.totalHits表示一共搜到多少个
        System.out.println("找到了" + hits.totalHits + "个");
        // 循环hits.scoreDocs数据,并使用indexSearch.doc方法把Document还原,再拿出对应的字段的值
        for (int i = 0; i < hits.scoreDocs.length; i++) {
            ScoreDoc sdoc = hits.scoreDocs[i];
            Document doc = indexSearch.doc(sdoc.doc);
            System.out.println(doc.get("filename"));
        }
        indexSearch.close();
    }
}

详细的解释在代码注释里都有了,就不做过多解释了。需要的jar包如下:

读取poi的类到poi官网下载,读取pdf的类到Apache PDFBox官网下载,这里用的1.8.13版本,2.0版本的调用方式与1.0版本已经不太一样了。

项目整体结构如下:

先运行类:

LuceneCreateIndex

会读取目录dataDirectory,即:

D:\Studying\poi\test\dataDirectory

下的文件,建立索引,索引会保存在目录indexDirectory,即:

D:\Studying\poi\test\indexDirectory

下,然后运行:

LuceneSearch

使用索引进行查询,就能看到效果了。

使用Lucene对doc、docx、pdf、txt文档进行全文检索功能的实现的更多相关文章

  1. CEBX格式的文档如何转换为PDF格式文档、DOCX文档?

    方正阿帕比CEBX格式的文档如何转换为PDF格式文档.DOCX文档? 简介: PDF.Doc.Docx格式的文档使用的非常普遍,金山WPS可以直接打开PDF和Doc.Docx文档,使用也很方便. CE ...

  2. java通过url在线预览Word、excel、ppt、pdf、txt文档

    java通过url在线预览Word.excel.ppt.pdf.txt文档中的内容[只获得其中的文字] 在页面上显示各种文档中的内容.在servlet中的逻辑 word: BufferedInputS ...

  3. PDF文件可以转换成txt文档吗

    PDF是一种便携式的文件格式,传送和阅读都非常方便,是Adobe公司开发的跨平台文件格式,它无论在哪种打印机上都可以保证精确的颜色和准确的打印效果.可是有点遗憾的是PDF格式一般不能在手机上打开,或者 ...

  4. C# 将内容写入txt文档

    <1>  FileStream fs = new FileStream(@"D:\text.txt", FileMode.Append); StreamWriter s ...

  5. QTP操作txt文档

    QTP可以在txt文件(文本文件中读取数据) 首先创造一个文档对象 set fso = createObject("scripting.filesystemobject") 然后用 ...

  6. 利用IDL将一个txt文档拆分为多个

    测试.txt文档,每47行的格式相同,通过代码每47行存为一个txt,txt文档命名为其第一行数据. 代码如下: file='G:\data\测试.txt' openr,lun,file,/Get_L ...

  7. PDF 补丁丁 0.4.1 版:新增嵌入中文字库、替换文档字库的功能

    PDF 补丁丁 0.4.1 版新增了嵌入中文字库.替换文档字库的功能. 嵌入汉字字库 历史上有一批黄底黑字的 PDF 文档.这批文档都具有相同的问题:没有嵌入字库.在一些设备上阅读时显示乱码.复制文本 ...

  8. 用matlab查找txt文档中的关键字,并把关键字后面的数据存到起来用matlab处理

    用matlab查找txt文档中的关键字,并把关键字后面的数据存到起来用matlab处理 我测了一组数据存到txt文件中,是个WIFI信号强度文档,里面有我们需要得到的数据,有没用的数据,想用matla ...

  9. WebService 实现BS环境与BS环境传递参数,根据参数生成txt文档

    客户端: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Client.as ...

随机推荐

  1. Linux光标移动异常

    刚刚安装完毕CentOS7.5,进行基础优化来着,发现我的光标具有如下神奇的故障. 无法移动到头部? 刚开始还以为是ISO镜像的问题,后校验了阿里云官网镜像的MD5值,和本地镜像MD5对比之后, 发现 ...

  2. 【转】Deep Learning(深度学习)学习笔记整理系列之(八)

    十.总结与展望 1)Deep learning总结 深度学习是关于自动学习要建模的数据的潜在(隐含)分布的多层(复杂)表达的算法.换句话来说,深度学习算法自动的提取分类需要的低层次或者高层次特征. 高 ...

  3. jsoup做http接口测试

    本文转载张飞的博客http://www.cnblogs.com/zhangfei/p/4359408.html在此感谢博主的分享! 最早用Jsoup是有一个小的爬虫应用要写,发现Jsoup较HttpC ...

  4. cas php

    CAS的php客户端实践—单点登录整合php程序 兄弟近日尝试将一个php程序以单点登录方式和原有的系统整合在一起.验证服务器选用的是CAS,其提供有相应的php客户端.整个过程如下:1.搭建CAS服 ...

  5. 爬取乌云上所有人民币和乌云符号的漏洞(python脚本)

    import httplib from HTMLParser import HTMLParser import urlparse import urllib from bs4 import Beaut ...

  6. linux下如何关闭某个tmux窗口

    答:分成两个步骤,如下: 1.列出当前的tmux窗口 jello@jello:~$ tmux ls 1: 1 windows (created Tue Jan 17 09:28:05 2019) [2 ...

  7. 2018-2019 Russia Open High School Programming Contest (Unrated, Online Mirror, ICPC Rules, Teams Preferred)

    前言 有一场下午的cf,很滋磁啊,然后又和dalao(见右面链接)组队打了,dalao直接带飞我啊. 这是一篇题解,也是一篇总结,当然,让我把所有的题目都写个题解是不可能的了. 按照开题顺序讲吧. 在 ...

  8. UVa 11021 麻球繁衍

    https://vjudge.net/problem/UVA-11021 题意:有k只麻球,每只活一天就会死亡,临死之前可能会生出一些新的麻球.具体来说,生i个麻球的概率为Pi.给定m,求m天后所有麻 ...

  9. 使用 if 语句

    与很多编程语言一样,if 表达式用来处理逻辑条件.在 R 中,逻辑条件通常表达为某个表达式返回的单值逻辑向量.例如,我们可以写一个简单的函数 check_positive,如果输入一个正数则返回 1, ...

  10. Android之提示Toast

    步骤: 设置监听事件步骤1.事件源,如按键 btn_simple2.事件 OnClick3.监听器new OnClickListener3.绑定事件源与事件 setOnClickListener(ne ...