第一次写博文,有错误请多指教。
在这里我用的是Lucene 3.0.2的包
这两天都在复习Lucene,因为要考试,复习的无聊之际,就尝试写个来检索D盘的简单的搜索引擎。
我们都知道,Lucene是一个,是一个开放源代码的全文检索引擎工具包,有了这个,我们就可干很多事情,比如简单的搜索引擎什么的,Lucene的效率很高。网上也有很多教程,大家可以上网查查这方面有关的资料。
接下来我就介绍下我的思路。
首先我们要获取D盘所有文件的基本信息,在这里我是获取了文件的文件名,还有文件的路径作为lucene的数据源。在这里我用了个多线程遍历整个D盘的文件。多线程的思路来源就是前几天老师教的那个多线程下载文件,比以前写的单线程快多了。
代码如下:
package visitUtil;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* @ClassName: LookAndVisitFile.java
* @author 作者姓名 Lin: email地址
* @version 创建时间:2016-1-6 下午2:53:40
* @Description TODO
*/
public class LookAndVisitFile {
String path = "D://";//遍历的路径
RandomAccessFile inxfile = null;
File file = null;
//遍历文件。并把文件信息写到D:/temp下.txt(内容包括文件名称,文件绝对路径)
public synchronized void visit(String path) throws IOException{
inxfile = new RandomAccessFile("D:/temp.txt","rw");
file = new File(path);
if(file.isDirectory()){
inxfile.seek(inxfile.length());
inxfile.writeChars(new String(file.getName().getBytes("gbk"),"gbk").trim()+","+new String(file.getAbsolutePath().getBytes("gbk"),"gbk")+","+file.lastModified()+"\r\n");
binaryVisit(file.listFiles(),3);
}
else if(file.isFile()){
//写入文件信息
inxfile.seek(inxfile.length());
inxfile.writeChars(new String(file.getName().getBytes("gbk"),"gbk").trim()+","+new String(file.getAbsolutePath().getBytes("gbk"),"gbk")+","+file.lastModified()+"\r\n");
}
inxfile.close();
}
/**
*
* @param files 目录下的多个文件
* @param num 线程的数量
*/
//遍历文件
private void binaryVisit(File[] files,int num) {
final int block = files.length/num;
for (int i = 1; i <= num; i++) {
int start = (i-1)*block;//计算文件遍历的起始位置
int end = i*block;//文件文件的结束位置
System.out.println(Thread.currentThread()+":=start="+start+":end="+end);
if((start-end)==0)continue;//加了个coninue速度快了一大截
startThread(files,start,end);
}
}
public void startThread(final File[] files,final int start,final int end){
new Thread(new Runnable() {
@Override
public void run() {
for (int j = start; j < end; j++) {
try {
Thread.sleep(100);
//System.out.println(files[j].getAbsolutePath());
visit(files[j].getAbsolutePath());//
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
}
public static void main(String[] args) throws IOException {
new LookAndVisitFile().visit("D://");
}
}
Lucene搜索部分
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
/**
* @ClassName: TestLucene.java
* @author 作者姓名 Lin: email地址
* @version 创建时间:2016-1-6 下午3:57:28
* @Description TODO
*/
public class TestLucene {
//表示索引的存放目录
String path = "D:/LuceneTestDircetory";//索引存放的目录位置,要先创建此文件夹
//
Directory dir;
public List<String[]> readFile(String filepath) throws Exception{
File file = new File(filepath);
List<String[]>sts = new ArrayList<String[]>();
//字符流读文件
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),"UTF-16"));//打开的格式用UTF-16的格式打开,才不会乱码,这个与前面写入文件的时候的格式有关
String line = null;
//每次读取一行就对文件的信息作出相应的解析 格式在写进文件的时候要确定好,在这里我是用,隔开信息
//本来想用Map值来存储,但是用List存放信息,更快
while((line=reader.readLine())!=null){
String[] temp;
temp = line.split(",");
if(temp.length==3)
{
sts.add(temp);
}
}
return sts;
}
//@Test
/* public void testxxx() {
try {
//String t = "`)0B0CBIY@A5}Q(ESKZS24G.jpg^D:\DataBackup\Tencent\494341886\Image\Image2\`)0B0CBIY@A5}Q(ESKZS24G.jpg^1374504260426"
readFile("D:\\temp.txt");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
//创建索引,并添加Document
public void createIndex() throws Exception{
System.out.println(path);
dir = FSDirectory.open(new File(path));
IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(Version.LUCENE_30), true ,MaxFieldLength.UNLIMITED);
List s = readFile("D://temp.txt");
for (int i = 0; i < s.size(); i++) {
Document doc = new Document();
doc.add(new Field("filename", ((String[])s.get(i))[0],Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));
doc.add(new Field("filepath", ((String[])s.get(i))[1],Store.YES,Field.Index.ANALYZED_NO_NORMS));
doc.add(new Field("filetime", ((String[])s.get(i))[2],Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));
writer.addDocument(doc);
}
writer.close();
}
//搜索部分
//这里主要是通过文件名,进行检索,大家可以用Reader()类对文本内容进行检索
public void Seacher(String keyword) throws Exception{
dir = FSDirectory.open(new File(path));//打开存放目录
IndexReader red = IndexReader.open(dir);//获取reader类
IndexSearcher searcher = new IndexSearcher(red);//获取检索类
QueryParser parse = new QueryParser(Version.LUCENE_30, "filename", new StandardAnalyzer(Version.LUCENE_30));
Query query = parse.parse(keyword+"~");
TopDocs docs = searcher.search(query, 1000);
//如果相似相似项找不到,就用通配符进行检索
if(docs.totalHits==0){
query = parse.parse(keyword+"*");
docs = searcher.search(query, 1000);
if(docs.totalHits==0){
System.out.println("找不到此类文件");
return ;
}
}
for (int i = 0; i < docs.totalHits; i++) {
System.out.println("文件名:"+searcher.doc(docs.scoreDocs[i].doc).get("filename")+" 路径是:"+searcher.doc(docs.scoreDocs[i].doc).get("filepath"));
SimpleDateFormat sFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String time = sFormat.format(new Date(Long.parseLong(searcher.doc(docs.scoreDocs[i].doc).get("filetime"))));
System.out.println("最后修改日期:"+time);
}
red.close();
searcher.close();
}
public static void main(String[] args) {
long startime = System.currentTimeMillis();
try {
//new TestLucene().testxxx();
//new TestLucene().createIndex();
new TestLucene().Seacher("火");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long endtime = System.currentTimeMillis();
System.out.println("花费是时间是:"+(endtime-startime)+"ms");
}
}
[程序搜索运行的结果如下]