- 论坛徽章:
- 0
|
本文转自:
http://hi.baidu.com/hupoo/blog/item/52b9748db2b37212b21bba1b.html
原文如下:
关键词: JNI ICTCLAS java c++
使用了北京师范大学陈天封装的java调用接口。由于ICTCLAS官方并没有发布DLL文件,但是发布了exe程序,和源码。陈天根据源码重新封装了DLL,并且做了相应的改动。
主要改动如下(copy自陈天):
因为免费版没有DLL提供,所以这个DLL是在分词.exe系统的源代码上改的,接口也和中科院的文档有些不一样.因为我觉得中科院提供的接口太多,用起来比较麻烦. 全部改动如下:
init函数:中科院的DLL没有参数,我提供两个参数,i=nOutputFormat,j=nOperateType,i和j的取值范围都是{0,1,2},有兴趣你可以改变一下init的方式试试看.
ICTCLAS_API bool ICTCLAS_SetOutputFormat(int nOutputFormat);
ICTCLAS_API bool ICTCLAS_SetOperType(int nOperateType);
这两个函数我把它删除掉了,因为已经在init中设置好了.
ICTCLAS_API bool ICTCLAS_SentenceProcess(char *sSentence,unsigned int nResultCount,char **sResult);经过试验,我认为这个函数和pargraphProcess差不多,所以和paragraphProcess合并成一个函数.
ICTCLAS_API bool ICTCLAS_FileProcess(char *sSourceFilename,char *sResultFilename);这是最不稳定的一个函数,当文件过大时容易产生错误. 这个错误并不是我造成的, 因为同一个文件试验原有系统也会出错,我没有修改这个错误,也不打算用这个函数,因为文件可以转换为段落,然后用paragraphProcess函数解析就可以,但是我仍然保留了这个函数.
exit()函数,我认为太麻烦,不是每次都记得要exit(),干掉了
改动后我经过多线程长时间并发测试,发现paragraphProcess函数是比较稳定的,做论文和学习是足够用了.最后,再次申明, 千万不要将本代码用于商业用途.
其实这个Java包中其他的都没有什么用,最关键的部分是:ICTCLAS.java,这个文件里面定义了DLL的三个接口函数:
public synchronized native boolean init(int i, int j);
public synchronized native String paragraphProcess(String sParagraph);
public synchronized native boolean fileProcess(String source,String target);
这三个是最重要的。
我把ICTCLAS类做成了一个单例,是因为我不知道多例并发这个DLL会出现什么问题。如下:
public synchronized static ICTCLAS getInstance(){
if (instance==null){
instance = new ICTCLAS();
}
return instance;
}
那么调用的时候,只需要
ICTCLAS ict = ICTCLAS.getInstance();
System.out.println(ict.paragraphProcess("巴拿马和美国都是国家地区,汉族是一个民族。"))
大家如果对ICTCLAS有兴趣,可以下载ICTCLAS的c++源码,看看,是MFC的.
ICTCLAS源码结构
Codes
│ ICTCLAS_WIN.cpp Windows界面的程序
│ ICTCLAS_Win.dsp
│ ICTCLAS_WIN.dsw
│ ICTCLAS_WIN.h
│ ICTCLAS_Win.exe 可执行程序
│ ICTCLAS_WinDlg.cpp
│ ICTCLAS_WinDlg.h
│ resource.h
│ StdAfx.cpp
│ StdAfx.h
│ log.txt 日志
│ ICTCLAS_Win.rc Windows界面的资源
│
├─Utility 共用函数模块
│ ContextStat.cpp
│ ContextStat.h
│ Dictionary.cpp
│ Dictionary.h
│ Utility.h
│ Utility.cpp
│
├─Unknown 未登录词识别模块
│ UnknowWord.cpp
│ UnknowWord.h
│
├─Tag HMM标注模块
│ Span.cpp
│ Span.h
│
├─Segment 词语切分模块
│ DynamicArray.h
│ NShortPath.cpp
│ NShortPath.h
│ Queue.cpp
│ Queue.h
│ SegGraph.cpp
│ Segment.cpp
│ Segment.h
│ DynamicArray.cpp
│ SegGraph.h
│
├─Result 结果生成模块
│ Result.cpp
│ Result.h
│
├─Data 概率数据文件
│ lexical.ctx
│ BigramDict.dct
│ coreDict.dct
│ nr.dct
│ nr.ctx
│ ns.ctx
│ ns.dct
│ tr.dct
│ tr.ctx
│
└─res Windows界面的资源
(2)下边进行做实验测速度.
学习使用JNI调用ICTCLAS的接口。(如果有必要,自己可以重新封装DLL供自己使用)。
程序如下:
package com.xjt.nlp.word;
public class ICTCLAS {
private static ICTCLAS instance=null;
private ICTCLAS() {
//第一个参数0(词语切分),1(一级标注),2(二级标注).
//第二个参数0(北大标准),1(973标准),2(XML).
init(0,0);
}
public synchronized static ICTCLAS getInstance(){
if (instance==null){
instance = new ICTCLAS();
}
return instance;
}
public synchronized native boolean init(int i, int j);
public synchronized native String paragraphProcess(String sParagraph);
public synchronized native boolean fileProcess(String source,String target);
public static void main(String[] args) {
ICTCLAS split1 = new ICTCLAS();
System.out.println("下边要处理的文本大小为48M");
long startTime=System.currentTimeMillis();
split1.fileProcess("c:\\1.txt","c:\\2.txt");
long endTime=System.currentTimeMillis();
System.out.println(endTime-startTime);//时间为毫妙
}
static{
System.loadLibrary("ICTCLAS");
}
}
工作环境:WinXP,赛扬1.2G,SDR256M
为了测试使用JNI调用大型文本的分词能力,我们处理一个48M的txt文本(内容是金庸的小说,譬如书剑恩仇录).经过处理后我们可以得到一个86M经过分分词的txt文本.
整个过程所花的时间为1607140ms=1607.140s=26.78m
平均处理速度1.8M/分钟.
如果不是使用JNI进行访问,而是直接使用其c++源码进行文本的分词
整个过程所花的时间为1552454ms=1552.454s=25.87m
则其平均处理速度为:1.85M/分钟
所以这么来说,使用JNI就在于时间花费在使用JNI调用dll的花费,其效果是足够我们使用的.
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/8780/showart_396800.html |
|