import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
//测试类
public class Exec {
public static void main(String[] args) {
// 创建窗体类变量
DemoWindow dw = new DemoWindow("基于Lucene的文件全文搜索系统");
// 将窗体的宽度和高度分别设置为屏幕宽度和屏幕高度的1/3,左上角位置也设置为屏幕宽度和屏幕高度的1/3处
Toolkit theKit = dw.getToolkit();
Dimension wndSize = theKit.getScreenSize();
dw.setBounds(wndSize.width / 3, wndSize.height / 3, wndSize.width / 3,
wndSize.height / 3);
// 点击关闭按钮可以退出程序
dw.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置窗体为可见
dw.setVisible(true);
}
}
// 界面窗体
class DemoWindow extends JFrame implements ActionListener {
// 显示命中文件名称的文本区
JTextArea jta = new JTextArea();
// 设置文本区的滚动条
int v = ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;
int h = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;
JScrollPane jsp = new JScrollPane(jta, v, h);
// 菜单
JMenuBar menuBar = new JMenuBar();
JMenu index = new JMenu("建立索引");
JMenuItem indexSource = new JMenuItem("指定需要索引的目录");
JMenuItem indexDestination = new JMenuItem("指定存放索引的目录");
JMenuItem createIndex = new JMenuItem("建立索引");
JMenu search = new JMenu("搜索");
JMenuItem keywordsSearch = new JMenuItem("关键词检索");
// Lucene索引器
Indexer indexer = null;
// Lucene搜索器
Searcher searcher = new Searcher();
// 需要建立索引的文件路径
String indexSourceStr = null;
// 存放索引的路径
String indexDestinationStr = null;
// 构造函数
public DemoWindow(String title) {
super(title);
// 添加文本区
add(jsp);
// 添加菜单
index.add(indexSource);
index.add(indexDestination);
index.addSeparator();
index.add(createIndex);
search.add(keywordsSearch);
menuBar.add(index);
menuBar.add(search);
setJMenuBar(menuBar);
// 取消部分菜单项的可用功能,这些菜单会随着操作的不断推进而逐次可用
indexDestination.setEnabled(false);
createIndex.setEnabled(false);
keywordsSearch.setEnabled(false);
// 添加事件监听器
indexSource.addActionListener(this);
indexDestination.addActionListener(this);
createIndex.addActionListener(this);
keywordsSearch.addActionListener(this);
}
// 响应单击菜单
public void actionPerformed(ActionEvent e) {
// 设置需要建立索引的文件所在目录
if (e.getSource() == indexSource) {
// 设置文件选择对话框
JFileChooser jfc = new JFileChooser();
// 该文件选择对话框只能打开文件目录
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
if (jfc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
// 将“指定存放索引的目录”菜单项设置为可用
indexDestination.setEnabled(true);
// 保存需要建立索引的文件路径
indexSourceStr = jfc.getSelectedFile().getPath();
}
}
// 设置保存索引的目录
else if (e.getSource() == indexDestination) {
// 设置文件选择对话框
JFileChooser jfc = new JFileChooser();
// 该文件选择对话框只能打开文件目录
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
if (jfc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
// 将“建立索引”菜单项设置为可用
createIndex.setEnabled(true);
// 保存存放索引的路径
indexDestinationStr = jfc.getSelectedFile().getPath();
}
}
// 处理建立索引
else if (e.getSource() == createIndex) {
// 建立索引器类变量
indexer = new Indexer(indexSourceStr, indexDestinationStr);
// 在新线程中建立索引
Thread t = new Thread(new ProcessIndex(indexer, keywordsSearch));
t.start();
}
// 处理搜索
else if (e.getSource() == keywordsSearch) {
// 显示输入信息对话框
String queryWords = JOptionPane.showInputDialog("请输入搜索词语:");
// 在文本区输出命中的文件名称结果
jta.setText(searcher.getResults(queryWords, indexDestinationStr));
}
}
}
// 建立索引的线程(由于索引比较耗时,所以单独使用一个线程来建立索引)
class ProcessIndex implements Runnable {
// 索引器类变量
Indexer indexer;
// 当索引结束后,设置该菜单项可用
JMenuItem jmi;
// 构造函数
public ProcessIndex(Indexer indexer, JMenuItem jmi) {
this.indexer = indexer;
this.jmi = jmi;
}
// 线程的工作方法,启动索引工作,并在索引建立后,设置该菜单项可用
public void run() {
try {
indexer.start();
jmi.setEnabled(true);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
// 索引器
class Indexer {
// 需要建立索引的文件路径
String indexSourceStr;
// 存放索引的路径
String indexDestinationStr;
// 构造函数
public Indexer(String indexSourceStr, String indexDestinationStr) {
this.indexSourceStr = indexSourceStr;
this.indexDestinationStr = indexDestinationStr;
}
// 调用index建立索引的函数
public void start() {
try {
File dataDir = new File(indexSourceStr);
File indexDir = new File(indexDestinationStr);
index(indexDir, dataDir);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
// 调用indexDirectory函数建立索引的函数
public void index(File indexDir, File dataDir) throws IOException {
// 建立索引写入器
// indexDir表示索引的存放地点
// new StandardAnalyzer()表示分析器
// true表示如已有索引则覆盖之
IndexWriter writer = new IndexWriter(indexDir, new StandardAnalyzer(),
true);
// 表示生成多文件索引文件(默认为复合索引)
writer.setUseCompoundFile(false);
// 递归调用indexDirectory函数
indexDirectory(writer, dataDir);
// 优化索引
writer.optimize();
writer.close();
}
// 被递归调用的建立索引函数
private void indexDirectory(IndexWriter writer, File dir)
throws IOException {
// 得到文件列表
File[] files = dir.listFiles();
// 循环所有文件
for (int i = 0; i < files.length; i++) {
File f = files[i];
// 如果是目录,则递归调用自己,否则如果文件扩展名为html,则调用indexFile函数对此文件建立索引
if (f.isDirectory()) {
indexDirectory(writer, f);
} else if (f.getName().endsWith(".html")) {
indexFile(writer, f);
}
}
}
// 对指定文件建立索引的函数
private void indexFile(IndexWriter writer, File f) throws IOException {
// 如果文件隐藏、不存在或者不可读取,则退出函数
if (f.isHidden() || !f.exists() || !f.canRead()) {
return;
}
// 在控制台输出建立索引的文件信息
System.out.println("Indexing " + f.getCanonicalPath());
// 建立索引关键代码
// 建立Document类变量
Document doc = new Document();
// 添加contents索引字段,内容为文件内容
doc.add(Field.Text("contents", new FileReader(f)));
// 添加url索引字段,内容为文件名称
String filename = f.getCanonicalPath();
String url = filename.substring(filename.lastIndexOf("mirror") + 7);
doc.add(Field.Keyword("url", url));
// 写入索引
writer.addDocument(doc);
}
}
// 搜索器
class Searcher {
// 根据搜索词和索引文件路径进行搜索的函数
public String getResults(String queryWords, String indexDestinationStr) {
// 返回结果
StringBuffer results = new StringBuffer();
try {
// 打开索引
File indexDir = new File(indexDestinationStr);
Directory fsDir = FSDirectory.getDirectory(indexDir, false);
IndexSearcher is = new IndexSearcher(fsDir);
// 解析查询词语
Query query = QueryParser.parse(queryWords, "contents",
new StandardAnalyzer());
// Query query = new TermQuery(new Term("contents", "java"));
// Query query = new TermQuery(new Term("contents", "application"));
// Query query = new TermQuery(new Term("contents", "java AND NOT
// application"));
// 搜索索引
Hits hits = is.search(query);
// 输出搜索结果
for (int i = 0; i < hits.length(); i++) {
Document doc = hits.doc(i);
results.append(doc.get("url") + "\n");
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
return results.toString();
}
}
[此贴子已经被作者于2010-12-14 09:40:18编辑过]