首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 服务器 > 云计算 >

java codebase的Hadoop施用中使用Darts

2012-12-25 
java codebase的Hadoop应用中使用Darts背景Darts是双数组的c (template)实现,用来存储、查询大规模词表非常

java codebase的Hadoop应用中使用Darts
背景

Darts是双数组的c++ (template)实现,用来存储、查询大规模词表非常方便。缺点是只能够使用“字符串完全匹配”,而不能查询“某个字符串是否是另外一个字符串的字串”这样的需求。

如下原因结合起来,促使要在java codebase中使用Darts:

1.        词表规模巨大,存储、查询效率很低

2.        Darts是c++实现,现有Hadoop codebase是java的,无法直接使用

技术思路:

1.        用c++进一步包装Darts接口(这一步必须要做,因为darts实现在.h中——template+inline牛B,默认使用方式是在c++project中直接包含头文件就能调用相关接口),并生成动态链接库

2.        用JNI(java native interface)进一步包装动态库,形成java接口

3.        在现有codebase中调用JNI

使用方法

这部分讲如何使用已经包装好的Darts。具体Darts是如何包装的,后面再详细说。

Darts JNI接口

接口定义在Darts.java文件中:

#include <jni.h>#include "darts.h"#include "MyDarts_Darts.h"#include <iostream>#include <string>#include <vector>#include <fstream>#include <algorithm>using namespace std;// the global variable for dictionaryDarts::DoubleArray thedict;/* * Class:     MyDarts_Darts * Method:    BuildDict * Signature: (Ljava/lang/String;Ljava/lang/String;)Z */JNIEXPORT jboolean JNICALL Java_MyDarts_Darts_BuildDict  (JNIEnv *env, jclass obj, jstring fileInput, jstring fileDictOutput){// get the file name stringsconst char *pFileInput = NULL;const char *pFileDictOutput = NULL;pFileInput = env->GetStringUTFChars (fileInput, false);pFileDictOutput = env->GetStringUTFChars (fileDictOutput, false);if (pFileInput == NULL || pFileDictOutput == NULL)return false;// load the terms and sortifstream in (pFileInput);if (!in){cerr << "Can not open the file of " << pFileInput << endl;return false;}string sTerm;vector<string> TermVec;while (getline (in, sTerm)){// trim itif ('\n' == sTerm.at (sTerm.length()-1) || '\t' == sTerm.at (sTerm.length()-1)){if ('\n' == sTerm.at (sTerm.length()-2) || '\t' == sTerm.at (sTerm.length()-2))sTerm.erase (sTerm.length()-2);elsesTerm.erase (sTerm.length()-1);}TermVec.push_back(sTerm);}sort (TermVec.begin(), TermVec.end());// it's necessary to build dictionary for darts// make TermVec as a c-style string array, and make the value arraychar ** pTermAry = (char **)malloc (TermVec.size() * sizeof(char *));vector<string>::iterator pIter = TermVec.begin();int i = 0;while (pIter != TermVec.end()){pTermAry[i] = (char*)pIter->c_str();pIter++;i++;}// build the dictionary for darts and output itthedict.build (TermVec.size(), pTermAry, 0, 0);thedict.save (pFileDictOutput);// clean upfree (pTermAry);env->ReleaseStringUTFChars(fileInput, pFileInput);env->ReleaseStringUTFChars(fileDictOutput, pFileDictOutput);return true;}/* * Class:     MyDarts_Darts * Method:    LoadDict * Signature: (Ljava/lang/String;)Z */JNIEXPORT jboolean JNICALL Java_MyDarts_Darts_LoadDict  (JNIEnv *env, jclass obj, jstring fileDictInput){// get the file name stringsconst char *pFileDictInput = NULL;pFileDictInput = env->GetStringUTFChars (fileDictInput, false);if (pFileDictInput == NULL)return false;// load the dictionaryif (-1 == thedict.open (pFileDictInput)){cerr << "Can not open the file of " << pFileDictInput << endl;return false;}env->ReleaseStringUTFChars(fileDictInput, pFileDictInput);return true;}/* * Class:     MyDarts_Darts * Method:    IsInDict * Signature: (Ljava/lang/String;)Z */JNIEXPORT jboolean JNICALL Java_MyDarts_Darts_IsInDict  (JNIEnv *env, jclass obj, jstring term){// get the file name stringsconst char *pTerm = NULL;pTerm = env->GetStringUTFChars (term, false);if (pTerm == NULL)return false;int iVal = 0;thedict.exactMatchSearch (pTerm, iVal);env->ReleaseStringUTFChars(term, pTerm);if (-1 == iVal)return false;elsereturn true;}
仔细看一下,接口中的数据类型都是JNI中的类型,如:jboolean、jstring等等,作为java数据类型和c++数据类型的桥梁,两者能够通过JNI函数相互转换。JNI编程可以查看具体资料,这里不多说。需要提醒一点的是,JNI中获取字符串的函数是GetStringUTFChars,将java String类型的字符串转成c字符串。从函数名字可以看到,它获取\返回的是UTF8编码的字符串,这也是上文强调无论是在构建字典的时候、还是在查询的时候,都要使用UTF8编码字符串的根本原因——不是Darts工具限制,而是JNI有这样的限制

5.        g++生成动态库

命令如下:

g++-I/usr/lib/jvm/java/include-I/usr/lib/jvm/java/include/linuxMyDarts_Darts.cpp -fPIC-shared -olibDarts.so

需要注意两个地方:

a)        需要注意的是一定要用‘-I’参数将包含jni.h的路径指明,否则找不到头文件,编译出错。

b)        文件名一定要用‘libxxx.so’,其中‘xxx’是动态库的名字,也是代码(无论java还是c++)中load动态库的名字。其余的,‘lib’小写。最常犯的错误是将文件名指定为‘xxx.so’。

至此,libDarts.so文件生成,按照上文的方法就可以正常使用。


参考文献:

【基础知识】使用Darts


热点排行