因此,很容易的我们想到,应该建立一个关键字与文件的相关映射,盗用ppt中的一张图,很明白的解释了这种映射如何实现。
在Lucene中,就是使用这种“倒排索引”的技术,来实现相关映射。
下面是Lucene的资料必出现的一张图,但也是其精髓的概括。
我们可以看到,Lucene的使用主要体现在两个步骤:
1 创建索引,通过IndexWriter对不同的文件进行索引的创建,并将其保存在索引相关文件存储的位置中。
2 通过索引查寻关键字相关文档。
简单例子:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
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.Store;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
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.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Range;
public class MyLucence {
private static MyLucence myLucence;
private static String content = "";
private static String INDEX_DIR = "D:\\luceneIndex";
private static String DATA_DIR = "D:\\luceneData";
private static Analyzer analyzer = null;
private static Directory directory = null;
private static IndexWriter indexWriter = null;
@SuppressWarnings("static-access")
public MyLucence getManager() {
if (myLucence == null) {
this.myLucence = new MyLucence();
}
return myLucence;
}
public static boolean createIndex(String path) {
Date date1 = new Date();
List<File> fileList = getFileList(path);
for (File file : fileList) {
content = "";
String type = file.getName().substring(
file.getName().lastIndexOf(".") + 1);
if ("txt".equalsIgnoreCase(type)) {
content += txt2String(file);
} else if ("doc".equalsIgnoreCase(type)) {
content += doc2String(file);
} else if ("xls".equalsIgnoreCase(type)) {
content += xls2String(file);
}
System.out.println("name:" + file.getName());
System.out.println("path:" + file.getPath());
System.out.println();
try {
// 首先,我们需要定义一个词法分析器
analyzer = new StandardAnalyzer(Version.LUCENE_40);
/**
* 第二步,确定索引文件存储的位置,Lucene提供给我们两种方式: 1 、本地文件存储 Directory
* directory = FSDirectory.open("/tmp/testindex"); 2 、内存存储
* Directory directory = new RAMDirectory();
*/
directory = FSDirectory.open(new File(INDEX_DIR));
File indFile = new File(INDEX_DIR);
if (!indFile.exists()) {
indFile.mkdirs();
}
// 第三步,创建IndexWriter,进行索引文件的写入:这里的IndexWriterConfig,据官方文档介绍,是对indexWriter的配置,其中包含了两个参数,第一个是目前的版本,第二个是词法分析器Analyzer
IndexWriterConfig config = new IndexWriterConfig(
Version.LUCENE_40, analyzer);
indexWriter = new IndexWriter(directory, config);
//第四步,内容提取,进行索引的存储:
//申请了一个document对象,这个类似于数据库中的表中的一行
Document document = new Document();
//把字符串存储起来(因为设置了TextField.TYPE_STORED,如果不想存储,可以使用其他参数,详情参考官方文档),并存储“表明”为"fieldname"
document.add(new TextField("filename", file.getName(),
Store.YES));
document.add(new TextField("content", content, Store.YES));
document.add(new TextField("path", file.getPath(), Store.YES));
//把doc对象加入到索引创建中
indexWriter.addDocument(document);
indexWriter.commit();
//关闭IndexWriter,提交创建内容
closeWirter();
} catch (Exception e) {
e.printStackTrace();
}
content = "";
}
Date date2 = new Date();
System.out.println("创建索引------耗时:"
+ (date2.getTime() - date1.getTime()) + "ms\n");
return true;
}
private static String txt2String(File file) {
String result = "";
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String s = null;
while ((s = br.readLine()) != null) {
result = result + "\n" + s;
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private static String doc2String(File file) {
String result = "";
try {
FileInputStream fis = new FileInputStream(file);
HWPFDocument doc = new HWPFDocument(fis);
Range rang = doc.getRange();
result += rang.text();
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private static String xls2String(File file) {
String result = "";
try {
FileInputStream fis = new FileInputStream(file);
StringBuilder sb = new StringBuilder();
jxl.Workbook rwb = Workbook.getWorkbook(fis);
Sheet[] sheet = rwb.getSheets();
for (int i = 0; i < sheet.length; i++) {
Sheet rs = rwb.getSheet(i);
for (int j = 0; j < rs.getRows(); j++) {
Cell[] cells = rs.getRow(j);
for (int k = 0; k < cells.length; k++)
sb.append(cells[k].getContents());
}
}
fis.close();
result += sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static void searchIndex(String text) {
Date date1 = new Date();
try {
directory = FSDirectory.open(new File(INDEX_DIR));
analyzer = new StandardAnalyzer(Version.LUCENE_40);
//第一步,打开存储位置
DirectoryReader ireader = DirectoryReader.open(directory);
//第二步,创建搜索器
IndexSearcher isSearcher = new IndexSearcher(ireader);
//第三步,类似SQL,进行关键字查询:我们创建了一个查询器,并设置其词法分析器,以及查询的“表名“为”fieldname“。查询结果会返回一个集合,类似SQL的ResultSet,我们可以提取其中存储的内容
QueryParser parser = new QueryParser(Version.LUCENE_40, "content",
analyzer);
Query query = parser.parse(text);
ScoreDoc[] hits = isSearcher.search(query, null, 1000).scoreDocs;
for (int i = 0; i < hits.length; i++) {
Document hitDocument = isSearcher.doc(hits[i].doc);
System.out.println("______________________");
System.out.println(hitDocument.get("filename"));
System.out.println(hitDocument.get("content"));
System.out.println(hitDocument.get("path"));
System.out.println("_______________________");
}
//第四步,关闭查询器等
ireader.close();
directory.close();
} catch (Exception e) {
e.printStackTrace();
}
Date date2 = new Date();
System.out.println("查看索引-----耗时:" + (date2.getTime() - date1.getTime())
+ "ms\n");
}
private static List<File> getFileList(String dirPath) {
File[] files = new File(dirPath).listFiles();
List<File> fileList = new ArrayList<File>();
for (File file : files) {
if (isTxtFile(file.getName())) {
fileList.add(file);
}
}
return fileList;
}
private static boolean isTxtFile(String fileName) {
if (fileName.lastIndexOf(".txt") > 0) {
return true;
} else if (fileName.lastIndexOf(".xls") > 0) {
return true;
} else if (fileName.lastIndexOf(".doc") > 0) {
return true;
}
return false;
}
private static void closeWirter() throws IOException {
if (indexWriter != null) {
indexWriter.close();
}
}
public static boolean deleteDir(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
deleteDir(files[i]);
}
}
file.delete();
return true;
}
public static void main(String[] args) {
File fileIndex = new File(INDEX_DIR);
if (deleteDir(fileIndex)) {
fileIndex.mkdir();
} else {
fileIndex.mkdir();
}
createIndex(DATA_DIR);
searchIndex("man");
}
}