1. 程式人生 > >海量的中文分片語件使用

海量的中文分片語件使用

海量的中文分片語件(HLSSplit.dll),是用C++寫的.在java下呼叫,就要用JNI技術.

前段時間做了一個.希望和大家分享一下.關於JNI技術,網上有很多的介紹,還不太瞭解的朋友,可以去網上看看,很簡單,看看就明白.

首先在寫一個類,這個是在JAVA下的呼叫類.

public class fc ......{

 
  public fc()......{
      HLSplitInit();
  }
 
  public synchronized native byte[] seg(byte[] text);//分詞
 
  public synchronized native void HLSplitInit();//初始化 
 
  public synchronized native void HLOpenUsrDict(byte[] fileName);//裝載使用者自定義詞典
 
 
  public static void main(String[] args) ......{
      fc a=new fc();
     
      char c=0;
      String str="供應止回閥"+c;
           
      //String str = "潘岳與邱曉華指出,這次核算得出的結果雖不完整,但也足以對現實全貌有所估計。這些數字再次證明了,環境危機正在越來越嚴重地制約經濟發展";
   
      String s=new String(a.seg(str.getBytes()));
     
      System.out.print(s);
  }

  static......{
      
    System.setProperty("java.library.path",System.getProperty("java.class.path"));
    System.loadLibrary("fc");
   
  }
}


其中的Main()函式裡面的內容,是顯示呼叫的方面,在實際的JNI中沒有作用.

char c=0;
String str="供應止回閥"+c; 這樣寫的原因是C中字串是有/0結束的.

執行JAVA fc.java ,然後執行JAVAH fc,產生fc.h標頭檔案.

下面建立用VC6.0建立一個空DLL工程,

然後向工程中新增fc.h,jni.h,HLSegFunc.h,HLPubDef.h,HLSSplit.lib

新增一個.cpp檔案,寫入下面的程式碼



#include <windows.h>
#include "jni.h"
#include "fc.h"
#include<stdio.h>
#include "HLSegFunc.h"
#include <string.h>



JNIEXPORT void JNICALL Java_fc_HLSplitInit(JNIEnv *, jobject)
{                      
    HLSplitInit();
}

JNIEXPORT void JNICALL Java_fc_HLOpenUsrDict (JNIEnv *env, jobject b, jbyteArray c)
{

    jbyte * arrayBody = (env)->GetByteArrayElements(c,0);
    char * ptr = (char *)arrayBody;
    HLOpenUsrDict(ptr);
  
}



JNIEXPORT jbyteArray JNICALL Java_fc_seg (JNIEnv *env, jobject b, jbyteArray c)
{
        
    jbyte * arrayBody = (env)->GetByteArrayElements(c,0);
    char * ptr = (char *)arrayBody;
  
    HANDLE h=HLOpenSplit();
    HLSplitWord(h ,ptr,HL_CAL_OPT_SEARCH);
    int j=HLGetWordCnt(h);
    jbyteArray d=(env)->NewByteArray(strlen(ptr)+j);
    int k=0;
    char *sep=" ";
    for(int i=0;i<j;i++)
    {
        SHLSegWord* pWord=HLGetWordAt(h , i);
        env->SetByteArrayRegion(d,k,strlen(pWord->s_szWord),(jbyte *)pWord->s_szWord);
        k+=strlen(pWord->s_szWord);
        env->SetByteArrayRegion(d,k,1,(jbyte *)sep);
        k+=1;
    }
    HLCloseSplit(h);
    return d;


}
然後,編譯就可以了.

把fc.class,fc.dll,HLSSplit.dll,HLSplitWord.dat,方面一個資料夾中,執行可以看到結果了.

我寫這個,是要在Nutch,實現中文分詞,不過,我試了試,感覺有這樣的問題:因為它是基於上面文的分詞,所以,不同的時候分詞的結果不同,這樣就給我們在搜尋的時候造成了問題,比如"美白是永遠的熱門話題",這句話的分詞結果是: 美/白/是/永遠/的/熱門/話題,而如果輸入"美白"兩個字,它就不分詞了,這樣就導致我們找不到上面的這句話了.產生這樣的原因,我認為是詞典裡面沒有"美白"這個詞.所以當你把它用到搜尋引擎的分詞是,要注意這點.

網上有很多研究Nutch中加入中文分詞技術文章,我覺得多少有些問題.過些天,我把我實現的過程,給大家分享一下,看看有沒有什麼問題.