最近在看Lucene in Action这本书的原著,第一步就是建立要建立文件索引,当然文件必须为统一的格式,Lucene不支持异构文件。
我练习了书中的listing 1.1:Indexer,由于我使用的是Lucene3.5版本,而书中使用的3.0,3.5和3.0是有一些差异的!
package org.apache.lucene.indexer; import java.io.File; import java.io.FileReader; import java.io.IOException; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Version; public class Indexer { private IndexWriter writer = null; /** * 完成索引建立 * @param args * @throws Exception */ public static void main(String[] args) throws Exception { if(args.length != 2) { throw new Exception("Usage: java"+Indexer.class.getName() +"<index dir> <data dir>"); } //存放索引的目录 String indexDir = args[0]; //需要被索引的文件存放的目录 String dataDir = args[1]; //用来测试Lucene建立索引所耗时间 long start = System.currentTimeMillis(); Indexer indexer = new Indexer(indexDir); int numIndexed = indexer.index(dataDir); indexer.close(); long end = System.currentTimeMillis(); System.out.println("Indexing "+numIndexed+" use "+(start-end)+"milliseconds"); } /** * 构造函数 * @param indexDir * @throws IOException */ public Indexer(String indexDir) throws IOException { // Creates an FSDirectory instance, trying to pick the best implementation given the current environment. Directory dir = FSDirectory.open(new File(indexDir)); //3.5版本之后使用这种方式来建立writer,参数:版本号,标准分词器 IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)); writer = new IndexWriter(dir, iwc); } /** * 把存放的文件建立为索引 * @param dataDir * @return writer.numDocs * @throws IOException */ private int index(String dataDir) throws IOException { //得到所有文件,listFiles为遍历文件 File[] files = new File(dataDir).listFiles(); for(int i=0; i<files.length; i++) { File f = files[i]; if(!f.isDirectory() && !f.isHidden() && f.canRead() && acceptFile(f)) { indexFile(f); } } return writer.numDocs(); } /** * 把文档加入Lucene的索引中 * @param f * @throws IOException */ private void indexFile(File f) throws IOException { //getCanonicalPath,更加通用,可以包含特殊字符,跨平台 //Returns the canonical pathname string of this abstract pathname. System.out.println("Indexing"+f.getCanonicalPath()); Document doc = getDocument(f); if(doc != null) { writer.addDocument(doc); } } /** * 对文档进行索引,此处只对文档的内容和名称域进行索引 * @param f * @return doc * @throws IOException */ private Document getDocument(File f) throws IOException { Document doc = new Document(); //内容可以不做存储 doc.add(new Field("contents", new FileReader(f))); //文件名存储,建立索引,但是依据情况没有必要对其进行分词 doc.add(new Field("filename", f.getCanonicalPath(),Field.Store.YES,Field.Index.NOT_ANALYZED)); return doc; } /** * 只允许对.txt文件作出处理,把它进行索引 * @param f * @return */ private boolean acceptFile(File f) { return f.getName().endsWith(".txt"); } /** * 当索引建立成功时,要记得关闭writer * @throws IOException * @throws CorruptIndexException */ private void close() throws CorruptIndexException, IOException { writer.close(); } }
在输入参数(D:\abc\lucene\index03 D:\abc\lucene)之后,运行结果为:
IndexingD:\abc\lucene\abc.txt IndexingD:\abc\lucene\car.txt IndexingD:\abc\lucene\hello.txt Indexing 3 use -1156milliseconds
以上程序中用到的类简要介绍:
IndexWriter
这个类可以建立一个新的索引或者打开一个已经存在的索引,
可以对索引进行增删改,但是不可以搜索和读取
Directory是IndexWriter存放索引的地方
FSDirectory在文件系统中存,RAMDirectory存在内存中(这样会更小、更快捷、应用关闭的时候就会销毁
但是缺点是不能持久化)这种方法适合于需要快速访问索引的时候,包括建立索引和搜索索引。
Analyer
IndexWriter不能索引文件除非它被分割成单个的词。
首先把文件的内容转变为有格式的形式。
它是一个抽象类,Lucene提供了一些实现方法。
分词器通过处理停词(不能作为区分文档的词,如a,the等)
把字符转为小写以便搜索的时候不区分大小写
一个合适的分词器能够对搜索的准确性提供很大帮助
Document
分词器需要一个包含独立字段的文档来索引
文档中有很多字段,这些字段都可以存放到索引中
Lucene只处理text格式的文档,
Feild
每个字段有若干个名称和其对应的值