JAVA文件搜索過(guò)程中如何得到各種文件內(nèi)容(office文件,PDF,郵件,mht,思維導(dǎo)圖等)
現(xiàn)在流行的搜索引擎Lucene, Elasticsearch處理文件搜索時(shí)一般使用 tika,使用tika 處理文件正文搜索還好,但搜索結(jié)果顯示正文等操作不是很方便,并且tika提取正文的速度比較慢。老版本還有很多外部依賴(lài)程序,安全性不好。
筆者給大家介紹一款調(diào)用方便,提取文件正文速度快,開(kāi)發(fā)方便的組件供大家參考。
“Graccvs正文提取組件”全部用go語(yǔ)言實(shí)現(xiàn),不依賴(lài)外部工具,效率高,安全性非常好。可以直接在操作系統(tǒng)上開(kāi)發(fā)使用,不要求JAVA等其他環(huán)境支持,而且從設(shè)計(jì)上避免了環(huán)境依賴(lài)或者解析器框架帶來(lái)的占用CPU過(guò)高和安全性問(wèn)題。組件提取文本速度快,質(zhì)量高,跨平臺(tái),支持多任務(wù)并發(fā),開(kāi)發(fā)簡(jiǎn)單成本低。提供多種語(yǔ)言接口及使用示例。
“Graccvs正文提取組件”支持很多文件格式:
A: pdf文件
B: office word文件 ".doc", ".odt", ".docx", ".dotm", ".docm"
C: wps文檔 ".wps"
D: office excel文件 ".xls", ".xlsx", ".xlsm", ".xltm"
E: wps表格 ".et"
F: office powerPoint文件 ".ppt", ".pptx", ".potm", ".pptm", ".ppsm"
G: wps演示 ".dps"
H:開(kāi)放文檔格式 ".ofd", 注:常見(jiàn)于“電子發(fā)票版式文件”
I:富文本類(lèi)型 ".rtf"
J: HTML頁(yè)面文件? ".html", ".htm", ".mht", ".mhtml"
K:郵件格式文件 ".eml", 注:默認(rèn)提取前5個(gè)附件
L:部分思維導(dǎo)圖格式文件 ".emmx", "xmind", "gmind"
M: UTF8編碼, Unicode編碼, Ansi編碼的文本文件,
?????????? ".txt", ".c", ".h", ".cpp", ".m", ".asp", ".aspx", ".cs", ".pas",
? ? ????? ".php", ".vb", ".bas", ".js", ".css", ".java", ".jsp", ".go",
?????????? ".pl", ".perl", ".ps", ".py", ".python", ".sql", ".rs", ".dart"
注:可以在配置文件中增加純文本文件后綴
N:幫助文件 “*.chm",注:此格式僅限Windows平臺(tái)
O:壓縮文件 ".zip", 注:默認(rèn)提取前5個(gè)文件
以下是使用Eclipse開(kāi)發(fā)工具,Java調(diào)用動(dòng)態(tài)鏈接庫(kù)示例:
調(diào)用過(guò)程:1:創(chuàng)建JAVA工程。2:工程導(dǎo)入調(diào)用DLL的擴(kuò)展包Native(jna-jpms-5.9.0.jar 和 jna-platform-jpms-5.9.0.jar)。3:拷貝 graccvs64.dll到工程中,LibGraccvs.java單元修改DLL位置(默認(rèn)在exe輸出位置)。4:實(shí)現(xiàn)提取文件正文函數(shù),點(diǎn)擊這里查看DLL函數(shù)詳細(xì)說(shuō)明。5:點(diǎn)擊這里下載完整工程包,這里下載最新DLL文件。
主要代碼單元LibGraccvs.java (函數(shù)的定義):
package graccvsDLL;
//
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
//
public interface LibGraccvs extends Library {
//默認(rèn)64位系統(tǒng),32位DLL或者接口最新DLL查看官網(wǎng)
@SuppressWarnings("deprecation")
LibGraccvs INSTANCE = (LibGraccvs) Native.loadLibrary("graccvs64.dll", LibGraccvs.class);
//----------------------以下為函數(shù)說(shuō)明----------------------
// 加載DLL,設(shè)置動(dòng)態(tài)庫(kù)需要的臨時(shí)文件夾,且對(duì)此文件夾要有讀寫(xiě)權(quán)限
void Load(Pointer tempDir);
//注冊(cè)軟件:
int Auth(Pointer corp, Pointer licText);
// 提供文件正文,并保存到目標(biāo)文件
// inFilePtr輸入文件地址, outFilePtr為T(mén)XT目標(biāo)文件文件地址
int ToTextFile(Pointer inFilePtr, Pointer outFilePtr);
//其他一個(gè)文件的正文,返回UTF-8字符串指針
//注意,調(diào)用此函數(shù)需要使用FreeString釋放指針內(nèi)存
Pointer ToString(Pointer inFilePtr);
//得到最后錯(cuò)誤日志
Pointer LastErr();
//釋放ToString函數(shù)返回的指針內(nèi)存
void FreeString(Pointer ptr);
// 提取Http/Https文件,返回字符串?dāng)?shù)據(jù)指針
// url=Http/Https地址
// fileExt=文件類(lèi)型(比如:".pdf"),
// timeout=超時(shí)設(shè)置,超過(guò)此數(shù)值系統(tǒng)終止下載文件。單位為毫秒,默認(rèn)為0(等待文件下載直到完成)
// httpParams=JSON格式header數(shù)據(jù)和cookie數(shù)據(jù),默認(rèn)為空
// 返回UTF-8編碼字符串?dāng)?shù)據(jù)指針(此指針需要使用FreeString函數(shù)釋放內(nèi)存)
Pointer HttpToString(Pointer url, Pointer fileExt, int timeout, Pointer httpParams);
// 下載Http文件,并提取文本,保存到目標(biāo)文件u
// outfile為T(mén)XT目標(biāo)文件文件地址,其他參數(shù)和HTTPTOSTRING參數(shù)相同
int HttpToTextFile(Pointer url, Pointer fileExt, Pointer outfile, int timeout, Pointer httpParams);
//---------------------異步批量處理相關(guān)函數(shù)---------------------
// 文件提取異步任務(wù), inFilePtr輸入文件地址, outTxtFilePtr為T(mén)XT目標(biāo)文件文件
// 如果提取某個(gè)文件錯(cuò)誤,則 結(jié)果文本的內(nèi)容如下格式: @ErrCode:錯(cuò)誤代碼, ErrMessage:錯(cuò)誤提示
void AddTask(Pointer inFilePtr, Pointer outTxtFilePtr);
// 異步提取Http文件任務(wù),參數(shù)同 HttpToTextFile 函數(shù)
void AddHttpTask(Pointer url, Pointer fileExt, Pointer outTxtFile, int timeout, Pointer httpParams);
// 開(kāi)始執(zhí)行異步任務(wù),返回值=1開(kāi)始執(zhí)行, 其他值未識(shí)別
// =2 免費(fèi)版不支持此功能,=3 沒(méi)有可以執(zhí)行的任務(wù) ,=4 當(dāng)前任務(wù)未完成
int AsyncStart();
// 停止任務(wù)
void AsyncStop();
// 一直等待,直到全部異步任務(wù)結(jié)束
void AsyncWait();
// 得到執(zhí)行異步任務(wù)的狀態(tài), =0 沒(méi)開(kāi)始, =1 正在處理中,=2 已中斷, =99 處理完成
int AsyncState();
// 設(shè)置執(zhí)行異步任務(wù)的并發(fā)數(shù)量(不大于軟件授權(quán)數(shù)量),返回并發(fā)數(shù)量
int AsyncMaxProcs(int num);
//---------------------異步批量處理相關(guān)函數(shù)---------------------
//程序結(jié)束前調(diào)用此函數(shù),否則釋放DLL會(huì)發(fā)生錯(cuò)誤
void Unload();
}
主要代碼單元TestMain.java (提取文件正文測(cè)試):
package graccvsDLL;
//
import java.io.UnsupportedEncodingException;
import java.util.*;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
//
public class TestMain {
public enum DllErrCode
{
TFE_OK,
TFE_UNKNOW,
TFE_FILE_NOTEXIST,
TFE_SAVE_ERROR,
TFE_OUTSIZE,
TFE_UNSUPPORTED ,
TFE_ERROR_INTERFACE ,
TFE_HTTP_ERR,
TFE_HTTP_FILE_NULL ,
TFE_LICENCE_ERR;
}
// 根據(jù)錯(cuò)誤類(lèi)型返回錯(cuò)誤信息
public static String codeText(DllErrCode code)
{
switch (code)
{
case TFE_OK:
return "ok";
case TFE_UNKNOW:
return "未知錯(cuò)誤";
case TFE_FILE_NOTEXIST:
return "提取源文件不存在";
case TFE_SAVE_ERROR:
return "保存目標(biāo)文件失敗";
case TFE_OUTSIZE:
return "提取的源文件超出設(shè)置的大小范圍";
case TFE_UNSUPPORTED:
return "不支持的提取文件格式";
case TFE_ERROR_INTERFACE:
return "得到接口失敗";
case TFE_HTTP_ERR :
return "HTTP下載文件失敗";
case TFE_HTTP_FILE_NULL :
return "HTTP文件為空";
case TFE_LICENCE_ERR:
return "軟件許可錯(cuò)誤";
default:
return "未知錯(cuò)誤2";
}
}
//字符串轉(zhuǎn)指針
public static Pointer getUtf8Pointer(String str){ ?
try {
byte[] data = str.getBytes("UTF-8");
Pointer p = new Memory(data.length + 1);
p.write(0, data, 0, data.length);
p.setByte(data.length, (byte)0);
return p;
}catch (UnsupportedEncodingException e) {
return null;
}
}
//utf8指針轉(zhuǎn)換為字符串
public static String utf8pointerToString(Pointer p){ ?
String str = p.getString(0);
try {
return new String(str.getBytes(), "UTF-8"); ?
}catch (UnsupportedEncodingException e){
return str;
}
}
// ------------------------提取正文并保存為文本文件------------------------
public static void testToTextFile(){ ?
Pointer prtInFile = getUtf8Pointer("test\\graccvs文件正文提取接口.pdf");
Pointer prtOutFile = getUtf8Pointer("test\\grcv001.txt"); ??
//
int r = LibGraccvs.INSTANCE.ToTextFile(prtInFile, prtOutFile); ?
DllErrCode code = DllErrCode.values()[r]; ?
if (code != DllErrCode.TFE_OK)
{
// 得到錯(cuò)誤方式1: 根據(jù)R值調(diào)用函數(shù)ErrText得到具體錯(cuò)誤信息, 此方式速度快
String err = codeText(code);
System.out.println("error from code:" + err);
// 方式2:調(diào)用DLL函數(shù),得到具體錯(cuò)誤信息, 此方式錯(cuò)誤信息更加準(zhǔn)確
Pointer p = LibGraccvs.INSTANCE.LastErr();
String err2 = utf8pointerToString(p);
System.out.println("error from dll lastErr:" + err2);
}
System.out.println("to text ok!");
}
// ------------------------提取正文,返回字符串指針------------------------
public static void testToString(){ ?
Pointer prtInFile = getUtf8Pointer("test\\簡(jiǎn)可信模板OCR識(shí)別工具幫助.docx"); ??
Pointer prtOutStr = LibGraccvs.INSTANCE.ToString(prtInFile);
try
{
String s = utf8pointerToString(prtOutStr);
System.out.println(s);
}
finally
{
LibGraccvs.INSTANCE.FreeString(prtOutStr); //調(diào)用此函數(shù)釋放字符串內(nèi)存,否則會(huì)導(dǎo)致內(nèi)存泄漏
}
}
// ------------------------HTTP提取正文并保存為文本文件------------------------
public static void testHttpToTextFile()
{ ?
Pointer prtUrl = getUtf8Pointer("https://www.gaya-soft.cn/dfs/v2/簡(jiǎn)可信模板OCR識(shí)別工具幫助.docx");
Pointer prtExt = getUtf8Pointer(".docx");
Pointer prtOutFile = getUtf8Pointer("test\\grcv002.txt");
// 調(diào)用DLL函數(shù)得到文件正文
int r = LibGraccvs.INSTANCE.HttpToTextFile(prtUrl, prtExt, prtOutFile, 0, null);
DllErrCode code = DllErrCode.values()[r];
//TFE_OK為提取完成,其他code調(diào)用codeText返回相同錯(cuò)誤
if (code != DllErrCode.TFE_OK)
{ ?
System.out.println("error from code, " + codeText(code));
}
else
{
System.out.println("testHttpToTextFile end");
}
}
// ------------------------HTTP提取正文,返回字符串指針------------------------
public static void testHttpToString()
{
Pointer prtUrl = getUtf8Pointer("https://www.gaya-soft.cn/dfs/v2/graccvs文件正文提取接口.pdf");
Pointer prtExt = getUtf8Pointer(".pdf");
String ?params = "{\"headers\":[{\"client_id\": \"g01x9\"}, {\"client_secret\": \"e23c89cc9fe\"}], \"cookies\":[{\"name\": \"ga\", \"value\": \"1020\", \"expires\":36000000, \"path\": \"/\"}]}";
Pointer prtParams = getUtf8Pointer(params);
int timeout = 60 * 1000; //超時(shí)設(shè)置,單位毫秒, 默認(rèn)為0
//
Pointer prtOutStr = LibGraccvs.INSTANCE.HttpToString(prtUrl, prtExt, timeout, prtParams);
try
{
String s = utf8pointerToString(prtOutStr);
System.out.println(s);
}
finally
{
LibGraccvs.INSTANCE.FreeString(prtOutStr); // 務(wù)必調(diào)用函數(shù)釋放字符串內(nèi)存
}
}
// ---------------異步批量文件提取,適合多線(xiàn)程處理很多文件---------------
// 文件提取任務(wù)
public static void asyncAddTask()
{ ??
// -----可以增加N個(gè)任務(wù) ???
Pointer prtInFile = getUtf8Pointer("test\\graccvs文件正文提取接口.pdf");
Pointer prtOutFile = getUtf8Pointer("test\\asyncOut001.txt");
LibGraccvs.INSTANCE.AddTask(prtInFile, prtOutFile); // 一個(gè)文件任務(wù)
Pointer prtInFile2 = getUtf8Pointer("test\\Adobe Intro.ofd");
Pointer prtOutFile2 = getUtf8Pointer("test\\asyncOut002.txt");
LibGraccvs.INSTANCE.AddTask(prtInFile2, prtOutFile2); // 一個(gè)文件任務(wù)
}
// Http文件提取任務(wù)
public static void asyncAddHttpTask()
{
// 可以增加N個(gè)任務(wù)
Pointer prtUrl = getUtf8Pointer("https://www.gaya-soft.cn/dfs/v2/簡(jiǎn)可信模板OCR識(shí)別工具幫助.docx");
Pointer prtExt = getUtf8Pointer(".docx");
Pointer prtOutFile = getUtf8Pointer("test\\asyncOut003.txt"); ?
int timeout = 90 * 1000; //超時(shí)設(shè)置,單位毫秒, 默認(rèn)為0
LibGraccvs.INSTANCE.AddHttpTask(prtUrl, prtExt, prtOutFile, timeout, null);
}
// 方式1:開(kāi)始任務(wù),等待全部任務(wù)完成
public static void asyncRun1()
{ ?
// 開(kāi)始任務(wù)
int r = LibGraccvs.INSTANCE.AsyncStart();
if (r == 1){ ?
LibGraccvs.INSTANCE.AsyncWait(); // 等待任務(wù)全部結(jié)束
System.out.println("方式1 -- 任務(wù)完成");
}else if (r == 2){
System.out.println("免費(fèi)版不支持此功能");
}else if (r == 3){
System.out.println("沒(méi)有可以執(zhí)行的任務(wù)");
}else if (r == 4){
System.out.println("當(dāng)前任務(wù)未完成");
}
}
// 方式2:判斷執(zhí)行情況,超時(shí)退出,主動(dòng)結(jié)束任務(wù)
public static void asyncRun2() ?
{
// 開(kāi)始任務(wù)
boolean isOver = false;
int r = LibGraccvs.INSTANCE.AsyncStart();
if (r == 1){
Date startDt = new Date();
// 5分鐘后結(jié)束任務(wù)
while((new Date()).getTime() - startDt.getTime() < 5 * 60 * 1000){
// 判斷任務(wù)情況, =0 沒(méi)開(kāi)始, =1 正在處理中,=2 已中斷, =99 處理完成
int x = LibGraccvs.INSTANCE.AsyncState();
if (x == 1){
try
{
Thread.sleep(500);
}
catch(InterruptedException e)
{
}
}else if (x == 99){
isOver = true; // 處理完成
break;
}else{
break;
}
}
//
if (!isOver){
LibGraccvs.INSTANCE.AsyncStop(); // 結(jié)束任務(wù)
} ??
System.out.println("方式2 -- 任務(wù)完成");
}else if (r == 2){
System.out.println("免費(fèi)版不支持此功能");
}else if (r == 3){
System.out.println("沒(méi)有可以執(zhí)行的任務(wù)");
}else if (r == 4){
System.out.println("當(dāng)前任務(wù)未完成");
}
}
public static void asyncTest()
{
//
LibGraccvs.INSTANCE.AsyncMaxProcs(8); // 同時(shí)運(yùn)行8個(gè)任務(wù)
//
asyncAddTask(); ????// 文件提取任務(wù)
asyncAddHttpTask(); // Http文件提取任務(wù)
// 執(zhí)行任務(wù)--方式1
asyncRun1();
// 執(zhí)行任務(wù)--方式2
asyncAddTask();
asyncAddHttpTask();
asyncRun2();
}
// ---------------異步批量文件提取,適合多線(xiàn)程處理很多文件---------------
public static void main(String[] args) {
Pointer prtPath = getUtf8Pointer("test");
// 提取文本需要的臨時(shí)文件夾,且對(duì)此文件夾要有讀寫(xiě)權(quán)限
LibGraccvs.INSTANCE.Load(prtPath);
// 設(shè)置軟件許可,免費(fèi)版都為空
Pointer corp = getUtf8Pointer("gaya-soft.cn");
Pointer licTxt = getUtf8Pointer("");
LibGraccvs.INSTANCE.Auth(corp, licTxt);
// 提取正文并保存為文本文件
testToTextFile(); //
// 提取正文,返回字符串指針
testToString();
// 提取HTTP提取正文, 并保存為文本文件
testHttpToTextFile();
// 提取HTTP提取正文, 返回字符串指針
testHttpToString();
// 異步批量文件提取測(cè)試
asyncTest();
//
LibGraccvs.INSTANCE.Unload();
//
String s2 = "over!";
System.out.println(s2);
}
} ??????