一永品、概述
主要用于打開各種不同的文檔。也就是我們需要處理不同格式的文檔击纬,比如word鼎姐、pdf
等,這個軟件就是用來處理不同格式的文檔更振。也是需要使用命令
java -jar tika-app-1.13.jar
運(yùn)行炕桨。直接file->open
打開相關(guān)的文檔,這樣它就會解析此文檔肯腕。
二献宫、入門(工程lucene-tika
)
先編寫創(chuàng)建索引的工具類:
IndexUtil.java
public void index(){
try {
File f = new File("E:/myeclipse/Lucene/complexFile/相關(guān)問題.docx");
Directory dir = FSDirectory.open(new File("E:/myeclipse/Lucene/index1"));
IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(Version.LUCENE_35, new MMSegAnalyzer()));
Document doc = new Document();
//doc.add(new Field("content", new Tika().parse(f)));
doc.add(new Field("content", new FileReader(f)));
writer.addDocument(doc);
writer.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
這里我們先不使用它tika
,看看索引的情況实撒,
TestIndex.java
@Test
public void testIndex(){
IndexUtil util = new IndexUtil();
util.index();
}
這里我們試驗(yàn)一下對一篇word
文檔進(jìn)行分詞姊途。然后我們使用luke
進(jìn)行查看,發(fā)現(xiàn)里面的信息都看不懂知态,完全不能滿足我們的要求吭净。在來看使用tika
的情況。注意:這里我們在添加文檔的時候也可以使用tika
的方式肴甸,不需要傳遞FileReader
寂殉。
- 第一種方式
IndexUtil.java
public String fileToTxt(File f){
//使用AutoDetectParser可以使Tika根據(jù)實(shí)際情況自動轉(zhuǎn)換需要使用的parser,不需要再手工指定
Parser parser = new AutoDetectParser();
InputStream is = null;//文件輸入流
try {
Metadata metadata = new Metadata();
//改變相關(guān)的內(nèi)容,Tika解析文檔時會生成的一組說明數(shù)據(jù)
metadata.set(Metadata.AUTHOR, "yj");
is = new FileInputStream(f);
//所有解析出來的內(nèi)容會放到它的子類BodyContentHandler中
ContentHandler handler = new BodyContentHandler();
//用來存儲需要填入的參數(shù),最少需要設(shè)置tikaParser本身
ParseContext context = new ParseContext();
context.set(Parser.class, parser);//為parser指定對象
parser.parse(is, handler, metadata, context);
//獲取metadata的信息
for(String name : metadata.names()){
System.out.println(name + ":" + metadata.get(name));
}
return handler.toString();//解析完之后會將結(jié)果存在handler中
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (TikaException e) {
e.printStackTrace();
}finally{
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
說明:在試驗(yàn)之前需要導(dǎo)入相關(guān)的依賴包。其中我們實(shí)例化AutoDetectParser
類來實(shí)例化一個Parser
對象原在,可以讓tika
根據(jù)不同的文檔類型自動轉(zhuǎn)換需要使用的Parser
友扰,不需要手動指定;而Metadata
表示解析文檔后生成的一些說明信息庶柿,如作者村怪、日期等內(nèi)容;ContentHandler
就是用來存放解析文檔后的內(nèi)容的浮庐;ParseContext
對象用來將之前的Parser
設(shè)置進(jìn)來甚负。
測試:
@Test
public void testTika01(){
IndexUtil util = new IndexUtil();
System.out.println(util.fileToTxt(new File("E:/myeclipse/Lucene/complexFile/相關(guān)問題.docx")));
}
說明:測試之后我們可以使用luke
或者tika
查看相關(guān)的內(nèi)容柬焕。
- 第二種方式
IndexUtil.java
public String tikaTool(File f) throws IOException, TikaException{
Tika tika = new Tika();
Metadata metadata = new Metadata();
metadata.set(Metadata.REALIZATION, "相關(guān)問題.docx");
//獲取metadata的信息
/*for(String name : metadata.names()){
System.out.println(name + ":" + metadata.get(name));
}*/
//當(dāng)然也是可以將信息存入到metadata中的
String str = tika.parseToString(new FileInputStream(f), metadata);
for(String name : metadata.names()){
System.out.println(name + ":" + metadata.get(name));
}
return tika.parseToString(f);
}
說明:可以看到這種方式相比第一種方式要簡單的多,但是注意梭域,默認(rèn)情況下Metadata
對象中是不會有數(shù)據(jù)的斑举,這和上面那種方式不一樣,當(dāng)然我們也可以使用parseToString
方法將相關(guān)信息設(shè)置到Metadata
中病涨。
三富玷、對多個文件進(jìn)行索引(工程lucene-tika1
)
首先我們建立索引FileIndexUtil.java
:
package cn.itcast.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Random;
import org.apache.commons.io.FilenameUtils;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
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.store.LockObtainFailedException;
import org.apache.lucene.util.Version;
import org.apache.tika.Tika;
import org.apache.tika.metadata.Metadata;
import com.chenlb.mmseg4j.analysis.MMSegAnalyzer;
public class FileIndexUtil {
private static Directory directory = null;
static {
try {
directory = FSDirectory.open(new File("E:/myeclipse/Lucene/index1"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static Directory getDirectory() {
return directory;
}
private static Document generatorDoc(File f) throws IOException{
Document doc = new Document();
Metadata metadata = new Metadata();
//通過tika進(jìn)行存儲
doc.add(new Field("content", new Tika().parse(new FileInputStream(f), metadata)));
//存儲頁數(shù),而像html這類文檔是沒有頁數(shù)的既穆,需要判斷
int pages = 0;
try{
pages = Integer.parseInt(metadata.get("xmpTPg:NPages"));
}catch(Exception e){
e.printStackTrace();
}
doc.add(new NumericField("page",Field.Store.YES, true).setIntValue(pages));
//存儲標(biāo)題
doc.add(new Field("title", FilenameUtils.getBaseName(f.getName()), Field.Store.YES, Field.Index.ANALYZED));
//存儲文件類型
doc.add(new Field("type", FilenameUtils.getExtension(f.getName()), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
doc.add(new Field("filename", f.getName(),Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("path", f.getAbsolutePath(),Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new NumericField("date", Field.Store.YES, true).setLongValue(f.lastModified()));
doc.add(new NumericField("size", Field.Store.YES, true).setIntValue((int) (f.length())));
return doc;
}
// 創(chuàng)建索引
public static void index(boolean hasNew) {
IndexWriter writer = null;
try {
writer = new IndexWriter(directory, new IndexWriterConfig(
Version.LUCENE_35, new MMSegAnalyzer()));
if (hasNew) {
writer.deleteAll();//如果我們要新建索引赎懦,那么將之前創(chuàng)建的刪除
}
File file = new File("E:/myeclipse/Lucene/complexFile");
Document doc = null;
for (File f : file.listFiles()) {
doc = generatorDoc(f);
writer.addDocument(doc);
}
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
說明:這里在創(chuàng)建索引時就不使用FileReader
了,而是使用Tika
對象幻工,我們將輸入流傳遞進(jìn)去励两。其他內(nèi)容和之前一樣,只是這里如果我們對一個html
文檔進(jìn)行索引時囊颅,這個索引是沒有頁數(shù)的当悔,所以我們需要判斷,不然會報(bào)異常迁酸。使用Tika
對文檔進(jìn)行解析之后我們再使用IndexWriter
進(jìn)行寫入。
測試:
@Test
public void testTika03(){
FileIndexUtil.index(true);
}
說明:在測試的時候俭正,雖然通過了測試奸鬓,但是卻報(bào)下面這個異常:
com.drew.lang.BufferBoundsException: Attempt to read from beyond end of underlying data source (requested index: 6, requested count: 2, max index: 5)
不知道是不是這個原因,導(dǎo)致我的索引感覺有問題掸读,最明顯的就是沒有進(jìn)行中文分詞串远,雖然我給出的分詞器是MMSEG
。最后我將tika
換成1.0版本就好了儿惫。而這里之所以沒有進(jìn)行中文分詞澡罚,是因?yàn)?code>MMSEG的包用的不對,應(yīng)該使用mmseg4j-all-1.8.5-with-dic.jar
肾请。這樣就正確了留搔。我們可以使用luke
進(jìn)行查看。
我們在編寫一個搜索方法:
SearchUtill.java
package cn.itcast.util;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
public class SearchUtill {
public void search01() throws Exception{
IndexSearcher searcher = new IndexSearcher(IndexReader.open(FileIndexUtil.getDirectory()));
TermQuery query = new TermQuery(new Term("content", "網(wǎng)絡(luò)"));
TopDocs tds = searcher.search(query, 20);
for(ScoreDoc sd : tds.scoreDocs){
Document doc = searcher.doc(sd.doc);
System.out.println(doc.get("title"));
}
searcher.close();
}
}
測試:
@Test
public void testTika04() throws Exception{
SearchUtill util = new SearchUtill();
util.search01();
}
說明:我們可以對相關(guān)關(guān)鍵詞進(jìn)行搜索铛铁,效率挺高的隔显。
四、高亮顯示
未完待續(xù)饵逐。括眠。。