lucene搜索关键字,高亮错位

咻咻秀秀修 发布于 2014/01/14 18:00
阅读 361
收藏 0

lucene3.6.2+jdk1.5+IKAnalyzers3.2.8

建立索引文件后,通过lucene自带的highlight组件进行高亮处理.得到结果显示不对.高亮的关键字错位.只有第一个关键字是正确的,之后的每一个关键字错位越来越多,每次一位...

代码如下

package cn.youngtop.lucene;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
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.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.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;
import org.wltea.analyzer.lucene.IKAnalyzer;

import cn.youngtop.lucene.filehandler.Excel2003ContentHandler;
import cn.youngtop.lucene.filehandler.Excel2007ContentHandler;
import cn.youngtop.lucene.filehandler.PDFContentHandler;
import cn.youngtop.lucene.filehandler.RTFContentHandler;
import cn.youngtop.lucene.filehandler.TextContentHandler;
import cn.youngtop.lucene.filehandler.Word2003ContentHandler;
import cn.youngtop.lucene.filehandler.Word2007ContentHandler;

public class LuceneUtils {

    private final String index_dir = "F://test//index";
    private IndexWriter writer;

    public LuceneUtils() {
        this("F://test//index");
    }

    public LuceneUtils(final String index_path) {
        try {
            
            IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_36, new IKAnalyzer());
            iwc.setOpenMode(OpenMode.CREATE);  
            writer = new IndexWriter(
                    new SimpleFSDirectory(new File(index_path)),iwc
                    );
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (LockObtainFailedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * @param file
     * @throws IOException
     */
    public void createIndex(File file) throws IOException {
        Document doc = new Document();
        doc.add(new Field("filename", file.getName(), Field.Store.YES,
                Field.Index.NOT_ANALYZED));
        doc.add(new Field("filepath", file.getAbsolutePath(), Field.Store.YES,
                Field.Index.NOT_ANALYZED));
        doc.add(new Field("content", getContent(file), Field.Store.NO,
                Field.Index.ANALYZED));
        writer.addDocument(doc);
        System.out.println(file.getName() + " 处理完成!");
    }

    /**
     * 目前只能处理 pdf,word03,07,excel03,07,rtf,以及各种文本文件
     *
     * @param file
     * @return
     * @throws FileNotFoundException
     */
    private String getContent(File file) throws FileNotFoundException {
        String filename = file.getName();
        FileInputStream fis = new FileInputStream(file);
        String content = "";
       /* if (filename.endsWith(".doc")) {
            content = new Word2003ContentHandler().getContent(fis);
        } else if (filename.endsWith(".docx")) {
            content = new Word2007ContentHandler().getContent(fis);
        } else if (filename.endsWith(".xls")) {
            content = new Excel2003ContentHandler().getContent(fis);
        } else if (filename.endsWith(".xlsx")) {
            content = new Excel2007ContentHandler().getContent(fis);
        } else if (filename.endsWith(".pdf")) {
            content = new PDFContentHandler().getContent(fis);
        } else if (filename.endsWith(".rtf")) {
            content = new RTFContentHandler().getContent(fis);
        } else {*/
            content = new TextContentHandler().getContent(fis);
        //}
        return content;
    }

    public static void main(String[] args) {
        try {
             new LuceneUtils().indexDirectory(new File("F:\\test\\small\\"));
            new LuceneUtils().search("关卡");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 递归处理文件夹
     *
     * @param dir
     * @throws IOException
     */
    private void indexDirectory(File dir) throws IOException {
        File[] files = dir.listFiles();
        for (int i = 0; i < files.length; i++) {
            File f = files[i];
            if (f.isDirectory()) {
                indexDirectory(f);
            } else
                createIndex(f);
        }
        writer.close();
    }

    public void search(String keyword) throws IOException {
        try {
            String field = "content";
            String field2 = "filepath";
            IndexReader ireader = IndexReader.open(FSDirectory.open(new File(
                    index_dir)));

            IndexSearcher isearcher = new IndexSearcher(ireader);
            QueryParser parser = new QueryParser(Version.LUCENE_36, "content",
                    new IKAnalyzer());
            IKAnalyzer analyzer = new IKAnalyzer();
            Query query = parser.parse(keyword);

            TopDocs topDocs = isearcher.search(query, 1000);
            System.out.println(keyword + "命中:" + topDocs.totalHits);
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            Highlighter hl = new Highlighter(new QueryScorer(query));
            for (int i = 0; i < scoreDocs.length; i++) {
                Document hitDoc = isearcher.doc(scoreDocs[i].doc);
                TokenStream ts = analyzer.tokenStream(field, new FileReader(
                        hitDoc.getValues(field2)[0]));
                String content = getContent(new File(
                        hitDoc.getValues(field2)[0]));

                String frament = hl.getBestFragment(ts, content);
                System.out.println(frament + "\r************************");
            }
            isearcher.close();
            analyzer.close();
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidTokenOffsetsException e) {
            e.printStackTrace();
        }
    }
}


package cn.youngtop.lucene.filehandler;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class TextContentHandler implements ContentHandler {

    public String getContent(InputStream is) {
        StringBuilder content = new StringBuilder();
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String s1 = null;

            while ((s1 = br.readLine()) != null) {
                content.append(s1 + "\r");
            }
            br.close();
            return content.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}

百度云盘源代码在此.http://pan.baidu.com/s/1tMv3g

效果图如下,该文件为utf-8编码

加载中
0
咻咻秀秀修
咻咻秀秀修

//    TokenStream ts = analyzer.tokenStream(field, new FileReader(hitDoc.getValues(field2)[0]));
    TokenStream ts = analyzer.tokenStream(field, new StringReader(content));

不使用FileReader,直接使用StringReader.ok了...

返回顶部
顶部