• hadoop上利用JNI分词


    虽然有streaming方式,但是碍于本人蹩脚的C++,还是决定由JNI方式来进行分词,下面是具体环境:

    hadoop:0.201 

    linux :2.6.16.60-0.21-TENCENT64-110923
    jdk:Java(TM) SE Runtime Environment (build 1.6.0_17-b04),Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01, mixed mode)
     
    TCWordSeg所必需的文件:
     
     
    其中libTCWordSeg.so是分词的库文件,而TCWordSeg.jar中包含了所有的类和方法原型。
    还有一个词典文件夹 data,其中包含了分词工具所必需的所有词典文件:
     
     
    为了能更好更方便的使用分词,写了一个包装的类,在写代码之前,将TCWordSeg.jar添加到buildpath中。WordSeg4J 代码如下:
     
    View Code
     1 import java.io.IOException;
     2 import org.mortbay.log.Log;
     3 import com.tencent.research.nlp.*;
     4  
     5 public class WordSeg4J {
     6  
     7 public static String dictDir = "data";
     8 public static int SEG_MODE =1; 
     9 static{
    10 System.loadLibrary("TCWordSeg");
    11 SEG_MODE = TCWordSeg.TC_POS | TCWordSeg.TC_S2D
    12 | TCWordSeg.TC_U2L | TCWordSeg.TC_T2S | TCWordSeg.TC_ENGU
    13 | TCWordSeg.TC_CN | TCWordSeg.TC_USR;
    14  
    15 try {
    16 TCWordSeg.TCInitSeg(to_cstr_bytes(dictDir));
    17 } catch (IOException e) {
    18 // TODO Auto-generated catch block
    19 System.out.println(e.getMessage());
    20 Log.info(e.getMessage());
    21 }
    22 }
    23  
    24 public static String segString(String str) {
    25 SWIGTYPE_p_void seghandle = TCWordSeg.TCCreateSegHandle(SEG_MODE);
    26 //System.out.println(str);
    27 String line_seg = "";
    28 /* 以 GBK 字节流的方式提供待切分句子 */
    29 try {
    30 TCWordSeg.TCSegment(seghandle, to_cstr_bytes(str));
    31 int rescount = TCWordSeg.TCGetResultCnt(seghandle);
    32 for (int i = 0; i < rescount; i++) {
    33 byte[] word_bytes = TCWordSeg.TCGetWordAt(seghandle, i);
    34 String word = new String(word_bytes, "GBK");
    35 line_seg += word + " ";
    36 }
    37 } catch (IOException e) {
    38 // TODO Auto-generated catch block
    39 System.out.println(e.getMessage());
    40 }
    41  
    42 return line_seg;
    43 }
    44  
    45 /*
    46  * 注意: 在 C 接口中传入参数类型为 char * 的地方, Java 接口中全部 使用参数类型 byte[], 并且 byte[] 数组必须以
    47  * '\0' 结束。 这是为了解决GBK 编码字符串在 C <-> Java 中转换的问题
    48  */
    49 public static byte[] to_cstr_bytes(String str) throws IOException {
    50 String s = str + '\0';
    51 return s.getBytes("GBK");
    52 }
    53 }

    ps:如果您经常使用这个类,建议将其打包为jar,推荐使用eclipse的fatjar工具,将TCWordSeg.jar一起打包成一个jar,或者用ANT打包。

    写完了包装类,就可以在Mapper或者Reducer中使用这个类的静态方法了。但是先别急着些驱动程序,还有两件事最好先完成:
    1)分别将libTCWordSeg.so和data文件夹打包成lib.tar和data.tar,当然也可以打包成zip或者jar、gzippedtar等形式。
    2)将上面两个tar文件上传到hdfs中,假设它们的hdfs路径分别为 /path/lib.tar 和/path/data.tar
    好了,现在就可以写驱动程序了,在写驱动程序的时候,需要注意利用hadoop的一个重要特性:DistributedCache,关于这个东西的详细介绍,网络上一大堆,自己可以去看。
    在驱动程序中,需要加入下面这么几行代码:
    View Code
    1 DistributedCache.createSymlink(conf); 
    2             
    3 Path filePath = new Path(" /path/lib.tar");
    4 String uriWithLink = filePath.toUri().toString(); DistributedCache.addCacheArchive(new URI(uriWithLink), conf); 
    5  
    6 Path filePath2 = new Path("/path/data.tar");
    7 String uriWithLink2 = filePath2.toUri().toString();
    8 DistributedCache.addCacheArchive(new URI(uriWithLink2), conf);    

     好了,之后用fatjar将程序打包,将TCWord.jar也一起打入,之后就可以在hadoop上运行程序了。

  • 相关阅读:
    学习规划
    一位十年的老司机告诉你什么是编程思想
    React开发
    一个简单的ipfs音乐播放器的实现
    React错误总结(三)
    React错误总结解决方案(二)
    mongoid模糊查询
    Rails accepts_nested_attributes_for表单嵌套的利器
    route_path
    "constantize" and "with_indifferent_access" method
  • 原文地址:https://www.cnblogs.com/ancientmoon/p/2696735.html
Copyright © 2020-2023  润新知