Java呼叫哈工大LTP介面(JNI方式實現)
阿新 • • 發佈:2018-12-22
哈工大LTP編譯使用譯文提到了哈工大LTP自然語言處理平臺的編譯使用,設計C++、Python和Java方式,相信可以參見其在GitHub主頁中提到的具體編譯方式和使用。這裡主要是關於在Java專案中呼叫C++。
Java呼叫C++(編譯得到DLL檔案),主要用JNI和JNA,其中JNA是基於JNI的。LTP的Java移植版本ltp4j是採用JNI的方式。Java呼叫C++編譯後的DLL檔案,對於DLL檔案的方式位置有一定的要求,需要在java.library.path
中,有如下幾種方式:
DLL檔案放在專案目錄下,即與
src
目錄同一級別
可以直接呼叫ltp4j中諸如Segmentor類及相關方法。DLL檔案放在自定義檔案中
在使用中需要自己顯示地呼叫庫,比如:
System.loadLibrary("segmentor"); // 分詞
方式一: 配置Java Build Path中選擇【Libraris】->【Native library location】,新增DLL檔案所在目錄。
Java Build Path(Eclipse)中配置 方式二:配置虛擬機器引數,【Run Configurations】->【Arguments】,在【VM arguments】中新增:
-Djava.library.path=DLL檔案所在目錄
- 方式三:動態配置(程式碼)
private void addDirToLiraryPath(String dirpath) {
try {
Field field = ClassLoader.class.getDeclaredField("sys_paths");
field.setAccessible(true);
String[] oldpath = (String[]) field.get(null);
String[] newPath = new String[oldpath.length + 1];
System.arraycopy(oldpath, 0 , newPath, 0, oldpath.length);
tem[oldpath.length] = dirpath;
field.set(null, newPath);
} catch (Exception e) {
e.printStackTrace();
}
}
完整的測試程式碼:
package test.hitltp;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import edu.hit.ir.ltp4j.NER;
import edu.hit.ir.ltp4j.Pair;
import edu.hit.ir.ltp4j.Parser;
import edu.hit.ir.ltp4j.Postagger;
import edu.hit.ir.ltp4j.SRL;
import edu.hit.ir.ltp4j.Segmentor;
import edu.hit.ir.ltp4j.SplitSentence;
public class TestHitLtp {
public static void main(String[] args) {
String sent = "國家主席習近平23日就倫敦恐怖襲擊事件向英國女王伊麗莎白二世致慰問電,對恐怖襲擊事件表示強烈的譴責,對無辜遇難者表示深切的哀悼,向傷者和遇難者家屬表示誠摯的慰問。"
+ "一天之內,習近平主席先後同來自大洋洲、亞洲和非洲的貴賓會晤,都談到了一個共同話題——“一帶一路”";
System.loadLibrary("splitsnt"); // 分句
System.loadLibrary("segmentor"); // 分詞
System.loadLibrary("postagger");// 詞性標註,需要分詞
System.loadLibrary("ner"); // 命名實體識別,需要分詞、詞性標註
System.loadLibrary("parser"); // 句法依存分析,需要分詞、詞性標註
System.loadLibrary("srl"); // 語義角色標註,需要分詞、詞性標註、句法依存,Java介面結果不正確
// jni檔案在相關類初始化時已載入,所以不用載入諸如segmentor_jni等dll檔案
String datadir = "nlpdatas/ltp-data-v3.3.1/ltp_data/";
// 分句
ArrayList<String> sents = new ArrayList<String>();
SplitSentence.splitSentence(sent, sents);
System.out.println(sents);
// 分詞
Segmentor.create(datadir + "cws.model");
List<String> words = new ArrayList<String>();
int size = Segmentor.segment(sent, words);
Segmentor.release();
System.out.println("size=" + size + "\n" + words);
System.out.println("pos====");
Postagger.create(datadir + "pos.model");
List<String> postags = new ArrayList<String>();
Postagger.postag(words, postags);
Postagger.release();
System.out.println("ner====");
NER.create(datadir + "ner.model");
List<String> ners = new ArrayList<String>();
NER.recognize(words, postags, ners);
NER.release();
for (int i = 0; i < size; i++) {
System.out.print(words.get(i) + "/" + postags.get(i) + "<" + ners.get(i) + "> | ");
}
System.out.println();
System.out.println("parser=======");
Parser.create(datadir + "parser.model");
List<Integer> heads = new ArrayList<Integer>();
List<String> deprels = new ArrayList<String>();
Parser.parse(words, postags, heads, deprels);
Parser.release();
for (int i = 0; i < size; i++) {
System.out.print(heads.get(i) + ":" + deprels.get(i) + "|");
}
System.out.println();
System.out.println("srl====");
SRL.create(datadir + "srl/");
List<Pair<Integer, List<Pair<String, Pair<Integer, Integer>>>>> srls = new ArrayList<Pair<Integer, List<Pair<String, Pair<Integer, Integer>>>>>();
SRL.srl(words, postags, ners, heads, deprels, srls);
SRL.release();
System.out.println(srls.size());
for (int i = 0; i < srls.size(); ++i) {
System.out.println(srls.get(i).first + ":");
for (int j = 0; j < srls.get(i).second.size(); ++j) {
System.out.println(" tpye = " + srls.get(i).second.get(j).first + " beg = "
+ srls.get(i).second.get(j).second.first + " end = " + srls.get(i).second.get(j).second.second);
}
}
}