這個想法的來源是,在以前剛學java時,有一本java基礎教程的書的附帶光盤里有作者寫的一個程序,可以方便初學者查找某些類在哪個實例里出現。當時沒有太在意,覺得作者的代碼很長。所以現在想自己也寫一個這樣的小程序。
整個程序里,除了Lucene的必要操作外,就是IO的基本操作了。因為要對某目錄下及其子目錄下的所有Java源文件進行索引,就要用到遞歸,同時要過濾掉非Java源文件。根據這種情況,設計了以下5個類。
異常類不是必要的,特意設計來包裝IO異常、文件異常和Lucene的異常。文件過濾工廠類的出現并不是故弄玄虛,只是不想太多代碼集中一起,就把文件過慮器的設計放到一個類里。下面是程序的完整代碼及注釋。
System.out.println("增加文件: " + file);
System.out.println("增加文件: " + file);
System.out.println("指定文件或目錄錯誤,沒有完成索引");
Field.Index.UN_TOKENIZED));
index(IndexWriter writer, File file, FileFilter filter)調用私有方法indexDirectory(IndexWriter writer, File file, FileFilter filter)完成文件的索引。
下面是IndexException異常類。
IndexException.java
package powerwind;
publicclass IndexException extends Exception {
public IndexException(String message) {
super("Throw IndexException while indexing files: " + message);
}
}
下面是FileFilterFactory類,返回一個特定的文件過濾器(FileFilter)。
FileFilterFactory.java
package powerwind;
import java.io.*;
publicclass FileFilterFactory {
/**
*靜態匿名內部類
*/
privatestatic FileFilter filter = new FileFilter() {
publicboolean accept(File file) {
long len;
return file.isDirectory()
(file.getName().endsWith(".java") &&
((len = file.length()) > 0) && len < 1024 * 1024);
}
};
publicstatic FileFilter getFilter() {
returnfilter;
}
}
main方法
/**
* main方法
*/
publicstaticvoid main(String[] args) throws Exception {
IndexJavaFiles ijf = new IndexJavaFiles();
Date start = new Date();
try {
IndexWriter writer = IndexWriterFactory.newInstance().createWriter("./index", true);
System.out.println("Indexing ...");
ijf.index(writer, new File("."), FileFilterFactory.getFilter());
System.out.println("Optimizing...");
writer.optimize();
writer.close();
Date end = new Date();
System.out.println(end.getTime() - start.getTime() + " total milliseconds");
} catch (IOException e) {
System.out.println(" caught a " + e.getClass() + "/n with message: " + e.getMessage());
}
}
SearchJavaFiles.java
package powerwind;
import java.io.*;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryParser.*;
import org.apache.lucene.search.*;
publicclass SearchJavaFiles {
private IndexSearcher searcher;
private QueryParser parser;
/**
*
*@paramsearcher
*/
public SearchJavaFiles(IndexSearcher searcher) {
this.searcher = searcher;
}
/**
*
*@paramfield
*@paramanalyzer
*/
publicvoid setParser(String field, Analyzer analyzer) {
setParser(new QueryParser(field, analyzer));
}
/**
*@paramparser
*/
publicvoid setParser(QueryParser parser) {
this.parser = parser;
}
/**
*
*@paramquery
*@returnHits
*@throwsSearchException
*/
public Hits serach(Query query) throws SearchException {
try {
returnsearcher.search(query);
} catch (IOException ioe) {
thrownew SearchException(ioe.getMessage());
}
}
/**
*
*@paramqueryString
*@returnHits
*@throwsSearchException
*/
public Hits serach(String queryString) throws SearchException {
if (parser == null)
thrownew SearchException("parser is null!");
try {
returnsearcher.search(parser.parse(queryString));
} catch (IOException ioe) {
thrownew SearchException(ioe.getMessage());
} catch (ParseException pe) {
thrownew SearchException(pe.getMessage());
}
}
/**
*
*輸出hits的結果,從start開始到end,不包括end
*
*@paramhits
*@paramstart
*@paramend
*@throwsSearchException
*/
publicstatic Hits display(Hits hits, int start, int end) throws SearchException {
try {
while (start < end) {
Document doc = hits.doc(start);
String path = doc.get("path");
if (path != null) {
System.out.println((start + 1) + "- " + path);
} else {
System.out.println((start + 1) + "- " + "No such path");
}
start++;
}
} catch (IOException ioe) {
thrownew SearchException(ioe.getMessage());
}
return hits;
}
進入討論組討論。
main方法
/**
*@paramargs
*/
publicstaticvoid main(String[] args) throws Exception {
String field = "contents";
String index = "./index";
finalint rows_per_page = 2;
finalchar NO = 'n';
SearchJavaFiles sjf = new SearchJavaFiles(new IndexSearcher(IndexReader.open(index)));
sjf.setParser(field, new StandardAnalyzer());
BufferedReader in = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
while (true) {
System.out.println("Query: ");
String line = in.readLine();
if (line == null line.length() < 2) {
System.out.println("eixt query");
break;
}
Hits hits = sjf.serach(line);
System.out.println("searching for " + line + " Result is ");
int len = hits.length();
int i = 0;
if (len > 0)
while (true) {
if (i + rows_per_page >= len) {
SearchJavaFiles.display(hits, i, len);
break;
} else {
SearchJavaFiles.display(hits, i, i += rows_per_page);
System.out.println("more y/n?");
line = in.readLine();
if (line.length() < 1 line.charAt(0) == NO)
break;
}
}
else
System.out.println("not found");
}
}
}
SearchException.java
package powerwind;
publicclass SearchException extends Exception {
public SearchException(String message) {
super("Throw SearchException while searching files: " + message);
}
}
完善設想:
1、文件格式:
能夠處理Z
ip文件Jar文件,索引里面的java源文件。
通過反射機制索引class類文件。
2、輸入輸出:
除控制臺輸入輸出外,還可以選擇從文件讀取查詢關鍵字,輸出查詢結果到文件。
3、用戶界面:
圖形界面操作,雙擊查詢結果的某條記錄可以打開相應文件。
4、性能方面
索引文件時,用緩存和多線程處理
進入討論組討論。
(出處:http://www.survivalescaperooms.com)