1. 程式人生 > >Java呼叫哈工大LTP介面(JNI方式實現)

Java呼叫哈工大LTP介面(JNI方式實現)

哈工大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中,有如下幾種方式:

  1. DLL檔案放在專案目錄下,即與src目錄同一級別
    可以直接呼叫ltp4j中諸如Segmentor類及相關方法。

  2. DLL檔案放在自定義檔案中
    在使用中需要自己顯示地呼叫庫,比如:

System.loadLibrary("segmentor"); // 分詞
  • 方式一: 配置Java Build Path中選擇【Libraris】->【Native library location】,新增DLL檔案所在目錄。

    Java Build Path

    Java Build Path(Eclipse)中配置
  • 方式二:配置虛擬機器引數,【Run Configurations】->【Arguments】,在【VM arguments】中新增:

-Djava.library.path=DLL檔案所在目錄
VM arguments

VM arguments方式配置
  • 方式三:動態配置(程式碼)
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);
        }
    }
}