说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

利用Hadoop Streaming处理二进制格式文件

HTML文档下载 WORD文档下载 PDF文档下载
Hadoop Streaming是Hadoop提供的多语言编程工具,用户可以使用自己擅长的编程语言(比如python、php或C#等)编写Mapper和Reducer处理文本数据。Hadoop Streaming自带了一些配置参数可友好地支持多字段文本数据的处理

编者按:Streaming是Hadoop的一个工具,用来创建和运行一类特殊的Map/Reduce作业。Streaming使用“标准输入”和“标准输出”与我们编写的Map和Reduce进行数据的交换。由此可知,任何能够使用“标准输入”和“标准输出”的编程语言都可以用来编写MapReduce程序。今天给大家分享一篇来自董西成的博文“利用Hadoop Streaming处理二进制格式文件”,文中介绍了如何使用Streaming处理二进制格式的文件。


CSDN推荐:欢迎免费订阅《Hadoop与大数据周刊》获取更多Hadoop技术文献、大数据技术分析、企业实战经验,生态圈发展趋势。


Hadoop Streaming是Hadoop提供的多语言编程工具,用户可以使用自己擅长的编程语言(比如python、php或C#等)编写Mapper和Reducer处理文本数据。Hadoop Streaming自带了一些配置参数可友好地支持多字段文本数据的处理,参与Hadoop Streaming介绍和编程,可参考我的这篇文章:“Hadoop Streaming编程实例”。然而,随着Hadoop应用越来越广泛,用户希望Hadoop Streaming不局限在处理文本数据上,而是具备更加强大的功能,包括能够处理二进制数据;能够支持多语言编写Combiner等组件。随着Hadoop 2.x的发布,这些功能已经基本上得到了完整的实现,本文将介绍如何使用Hadoop Streaming处理二进制格式的文件,包括SequenceFile,HFile等。

注:本文用到的程序实例可在百度云:hadoop-streaming-binary-examples 下载。

在详细介绍操作步骤之前,先介绍本文给出的实例。假设有这样的SequenceFile,它保存了手机通讯录信息,其中,key是好友名,value是描述该好友的一个结构体或者对象,为此,本文使用了google开源的protocol buffer这一序列化/反序列化框架,protocol buffer结构体定义如下:

option java_package = "";
option java_outer_classname="PersonInfo";
message Person {
  optional string name = 1;
  optional int32 age = 2;
  optional int64 phone = 3;
  optional string address = 4;
}

SequenceFile文件中的value便是保存的Person对象序列化后的字符串,这是典型的二进制数据,不能像文本数据那样可通过换行符解析出每条记录,因为二进制数据的每条记录中可能包含任意字符,包括换行符。

一旦有了这样的SequenceFile之后,我们将使用Hadoop Streaming编写这样的MapReduce程序:这个MapReduce程序只有Map Task,任务是解析出文件中的每条好友记录,并以name \t age,phone,address的文本格式保存到HDFS上。

1. 准备数据

首先,我们需要准备上面介绍的SequenceFile数据,生成数据的核心代码如下:

final SequenceFile.Writer out =
        SequenceFile.createWriter(fs, getConf(), new Path(args[0]),
                Text.class, BytesWritable.class);
Text nameWrapper = new Text();
BytesWritable personWrapper = new BytesWritable();
System.out.println("Generating " + num + " Records......");
for(int i = 0; i < num; i++) {
  genOnePerson(nameWrapper, personWrapper);
  System.out.println("Generating " + i + " Records," + nameWrapper.toString() + "......");
  out.append(nameWrapper, personWrapper);
}
out.close();

当然,为了验证我们产生的数据是否正确,需要编写一个解析程序,核心代码如下:

Reader reader = new Reader(fs, new Path(args[0]), getConf());
Text key = new Text();
BytesWritable value = new BytesWritable();
while(reader.next(key, value)) {
  System.out.println("key:" + key.toString());
  value.setCapacity(value.getSize()); // Very important!!! Very Tricky!!!
  PersonInfo.Person person = PersonInfo.Person.parseFrom(value.getBytes());
  System.out.println("age:" + person.getAge()
          + ",address:" + person.getAddress()
          +",phone:" + person.getPhone());
}
reader.close();

需要注意的,Value保存类型为BytesWritable,使用这个类型非常容易犯错误。当你把一堆byte[]数据保存到BytesWritable后,通过BytesWritable.getBytes()再读到的数据并不一定是原数据,可能变长了很多,这是因为BytesWritable采用了自动内存增长算法,你保存的数据长度为size时,它可能将数据保存到了长度为capacity(capacity>size)的buffer中,这时候,你通过BytesWritable.getBytes()得到的数据最后一些字符是多余的,如果里面保存的是protocol buffer序列化后的字符串,则无法反序列化,这时候可以使用BytesWritable.setCapacity (value.getSize())将后面多余空间剔除掉。

2. 使用Hadoop Streaming编写C++程序

为了说明Hadoop Streaming如何处理二进制格式数据,本文仅仅以C++语言为例进行说明,其他语言的设计方法类似。

先简单说一下原理。当输入数据是二进制格式时,Hadoop Streaming会对输入key和value进行编码后,通过标准输入传递给你的Hadoop Streaming程序,目前提供了两种编码格式,分别是rawtypes和  typedbytes,你可以设计你想采用的格式,这两种编码规则如下(具体在文章“Hadoop Streaming高级编程”中已经介绍了):

rawbytes:key和value均用【4个字节的长度+原始字节】表示

typedbytes:key和value均用【1字节类型+4字节长度+原始字节】表示

本文将采用第一种编码格式进行说明。采用这种编码意味着你不能想文本数据那样一次获得一行内容,而是依次获得key和value序列,其中key和value都由两部分组成,第一部分是长度(4个字节),第二部分是字节内容,比如你的key是dongxicheng,value是goodman,则传递给hadoop streaming程序的输入数据格式为11 dongxicheng 7 goodman。为此,我们编写下面的Mapper程序解析这种数据:

int main() {
 string key, value;
 while(!cin.eof()) {
  if(!FileUtil::ReadString(key, cin))
   break;
  FileUtil::ReadString(value, cin);
  Person person;
  ProtoUtil::ParseFromString(value, person);
  cout << person.name() << "\t" << person.age()
       << "," << person.address()
       << "," << person.phone() << endl;
 }
 return 0;
}

其中,辅助函数实现如下:

class ProtoUtil {
 public:
  static bool ParseFromString(const string& str, Person &person) {
   if(person.ParseFromString(str))
    return true;
   return false;
  }
};
class FileUtil {
 public:
  static bool ReadInt(unsigned int *len, istream &stream) {
   if(!stream.read((char *)len, sizeof(unsigned int)))
    return false;
   *len = bswap_32(*len);
   return true;
  }
  static bool ReadString(string &str, istream &stream) {
   unsigned int len;
   if(!ReadInt(&len, stream))
    return false;
   str.resize(len);
   if(!ReadBytes(&str[0], len, stream))
    return false;
   return true;
  }
  static bool ReadBytes(char *ptr, unsigned int len, istream &stream) {
   stream.read(ptr, sizeof(unsigned char) * len);
   if(stream.eof()) return false;
   return true;
  }
};

该程序需要注意以下几点:

(1)注意大小端编码规则,解析key和value长度时,需要对长度进行字节翻转。

(2)注意循环结束条件,仅仅靠!cin.eof()判定是不够的,仅靠这个判定会导致多输出一条重复数据。

(3)本程序只能运行在linux系统下,windows操作系统下将无法运行,因为windows下的标准输入cin并直接支持二进制数据读取,需要将其强制以二进制模式重新打开后再使用。

3. 程序测试与运行

程序写好后,第一步是编译C++程序。由于该程序需要运行在多节点的Hadoop集群上,为了避免部署或者分发动态库带来的麻烦,我们直接采用静态编译方式,这也是编写Hadoop C++程序的基本规则。为了静态编译以上MapReduce程序,安装protocol buffers时,需采用以下流程(强调第一步),

./configure –disable-shared
make –j4
make install

然后使用以下命令编译程序,生成可执行文件ProtoMapper:

g++ -o ProtoMapper ProtoMapper.cpp person.pb.cc `pkg-config –cflags –static –libs protobuf` -lpthread

在正式将程序提交到Hadoop集群之前,需要先在本地进行测试,本地测试运行脚本如下:

#!/bin/bash
HADOOP_HOME=/opt/dong/yarn-client
INPUT_PATH=/tmp/person.seq
OUTPUT_PATH=file:///tmp/output111
echo "Clearing output path: $OUTPUT_PATH"
$HADOOP_HOME/bin/hadoop fs -rmr $OUTPUT_PATH
${HADOOP_HOME}/bin/hadoop jar\
   ${HADOOP_HOME}/share/hadoop/tools/lib/hadoop-streaming-2.2.0.jar\
  -D mapred.reduce.tasks=0\
  -D stream.map.input=rawbytes\
  -files ProtoMapper\
  -jt local\
  -fs local\
  -input $INPUT_PATH\
  -output $OUTPUT_PATH\
  -inputformat SequenceFileInputFormat\
  -mapper ProtoMapper

注意以下几点:

(1)使用stream.map.input指定输入数据解析成rawbytes格式

(2) 使用-jt和-fs两个参数将程序运行模式设置为local模式

(3)使用-inputformat指定输入数据格式为SequenceFileInputFormat

(4)使用mapred.reduce.tasks将Reduce Task数目设置为0

在本地tmp/output111目录下查看测试结果是否正确,如果没问题,可改写该脚本(去掉-fs和-jt两个参数,将输入和输出目录设置成HDFS上的目录),将程序直接运行在Hadoop上。

原文链接:利用Hadoop Streaming处理二进制格式文件       (编辑/刘亚琼  审校/仲浩)

WIN32 API-VB资料 WIN32 API的分类介绍 -VB资料 Win95系统API函数大揭秘 作者:何发武 -VB资料 把图标放在WIN95的系统托盘中-VB资料 打开/关闭光驱门-VB资料 调用API函数设计ABOUT窗口 -VB资料 功能强大的SendMessage函数 -VB资料 简单计算函数的编写过程-VB资料 将文件大小变成相应的字符串-VB资料 可以直接用API改变textbox的扩展样式-VB资料 快速读取TextBox第N行的数据 -VB资料 VB利用 API 可以直接拨号 VB利用API 使Text框只读 VB利用API创建文件目录 VB利用API函数实现VB特殊窗体的两种方法 VB利用API函数实现无TittleBar窗体的移动 VB利用API在VB5.0中实现清除文档名 VB利用App.PrevInstance防止同一程序执行多次 VB判断应用程序是否仍在运行并设置焦点 巧用VISUAL BASIC的RND()函数 让你的程序不在任务栏中显示 -VB资料 VB如何不用API使文本框属性只读? VB如何从文件中提取图标 VB如何关闭/重新启动计算机? VB如何建立快捷方式? VB如何让窗口始终在最前面? VB如何使你的程序同文件扩展名建立关联? VB如何提高调用WINDOWS API函数编程技巧 VB如何为你的应用程序设置热键? VB如何隐藏鼠标指针 VB如何用api检查任务栏中有多少种输入法 MFC程序的结构问题? 一个酷似chinaasp的社区,需要你的支持。嘿……实在做得很好,送分!!!随便给朋友做做广告 7:30之前一定要交。。。。急。。。。!!!! 文件改名用哪个函数啊? 为什么我的windows2000pro共享文件不能访问????? 在VB.Net中的TabControl有一个OwnerDraw的功能,但不知到如何才能将上面的Item画成有曲线的 一个程序员的路是怎样开始的?我该选择VB还是C语言? 那里有动态加载控件的文章??? 哪位高手告知学习C++/VC++的步骤和各阶段应看的书。 湖北的有查到分数的没有,怎么查,我天天晚上做恶梦,救救我! 能否请高手指教关于开在开机时屏蔽热键的问题(del+alt+ctrl)?高分送上! 请教语音卡高手:并线录音和串线录音有何不同?电压驱动和话音驱动有什么不同? 一个时钟周期是多长时间? 请问各位谁做过(正在做)用MODEM来录电话语音的?进来打个招呼,探讨探讨。 有人用过CIPAddressCtrl这个控件吗?怎么用?为什么MSDN上说它有一个GetAddress的方法,但我在使用中却找不到这个方法? 请问广东省的高程成绩在哪儿查询,怎样才可以查询到呀???? 运行时的这个异常提示,什么意思?如何解决 关于数据库的一个问题 tmd.江西的软考办的人吃虱去了。 各位大哥:如果在使用的时候,字体变大,是什么原因?有什么办法跟踪吗? 救命啊。。。。。。。高手该出手拉。。 可不可以在一个树控件中的一个节点下面再加另外一个结控件?怎么搞? a question about form evaluation about form evaluation 她现在就睡在我的身边,她长的很丑,大脑袋,小眼睛、身子特长腿特短,简直是一无是处,还让我守护着她睡觉,TMD我比死了还难受,好痛苦啊。。。。。。 在excel2000中,如何在单元格中画对角线(就是常见的表头)? 如何使win98登录WIN2K server中? 各位大哥,请问怎样汉化C++Builder中的英文提示框(祥见内容部分)?谢谢! 请问怎么在sqlserver的用户子定义中是用循环啊! 真奇怪,我只是想通过accept得到的sockaddr_in来得到的IP再用gethostbyaddr得到主机名,但是死循环,请我看看错在哪里?我给分的 quickrep建立的报表,一对多表如何设置,为什么我设置报表的dataset属性为从表时,预览出现主表数据无法显示出现unkown错误,而从表可以。 怎样让“星际”通过代理服务器上网? oracle优化 用ADO控件操作数据库,对于关键字重复错误如何捕获? 深圳的朋友,有没有人知道深大通信(深大电话)? 急!!!!!!!!怎样将excel导入数据库(access),重要的是要能在修改后返回excel?而且excel表中的几张表的表头格式不一样? 考考你的UNIX/C 请问server.htmlencode()有什么用处?? 喜欢听白桦林吗? 不好意思,问个问题! 请问如何在下拉框中添加图片?有重谢! 50元找一控件.(在Delphi中怎样把JPG文件插入到SQL Server数据库的Image字段中) 偶想做pb的登录界面,就是填入正确的密码账号方可使用软件,偶把主创体设为mdi frame,登录子窗体为response,但是运行后,不登录子窗体,主窗体也能使用(菜单有响应),怎么版?另外,子窗体右上方的 x 键怎么去掉?//牛虻 在一个页面里调用两个存储过程,并对其中一个存储过程的记录来控制分页显示,请问如何实现 请问在VIEW,APP类和FRAME类中都能接收相同菜单的消息,如newfile?谢了大侠们 linux菜鸟询问小问题,希望回答! DataGrid中的值编写入网页 送分题,快来、快来啊!(如何用CreateFont显示WINDOWS默认字体) 我要用delphi将 sql server 的 .mdf 和 .ldf 加载到数据库中怎么做?? 如何学习dll的编程,up者有分! 请数据库高手指点,错在何处 数字压力传感器一般多少钱? 如何自制冰淇淋 12v电瓶充电器有电压没电流和电池一起量也没电流,串联的万用表 求推荐一款数字压力传感器,质量和价格都能接受的? 如何自制哑铃 自制汽车12V电瓶的充电器,变压器的输出电压该是多少?注:电瓶是12V60Ah的 数字压力传感器哪些牌子比较好? 26.理想电压源与理想电流源并联,对外部电路而言,它等效于什么是等效于理想电流源还是理想电压源 什么昆虫有毒 数字压力传感器Maxair的怎么样? 已知如下图所示,I1=2A,R1=8欧,R2=R3=R4=6欧,求电路中各支路电流和理想电流源的电压U1 英语翻译光电传感器 英文怎么说? 只要电路两端有电压电路中就一定有电流,这句话错在哪里恩 为什么地球上只有人类文明这一种文明?地球上在出现了生物之后,经过漫长的变异和发展,逐渐形成了各种各样的生物.从理论上讲,任何一种生物都应该可以发展出它们自己的文明,因为,人类不 人类认识地球经历了哪几个阶段 关于电压下列说法正确的是 A电路两端有电压,电路中就一定有电流 B电路中无电流,电路两端就一定无电压C电路两端必须有电压,才可能有电流D电路中有无电流,与电压无关【说明理由】 地球的熵值是在增加吗?人类文明能坚持1亿年吗话不用说那么多,我就是想和各位探讨一下.尽量发表自己的看法.还有我想问的是“地球”的熵值是在增加么? 人类对地球形状的认识过程 电压控制的电压源和电流控制的电路原在都表达成电压么?如图 关于电流,电压和电阻,下列说法正确的是 A只要导体接入电路,电路中就有电流关于电流、电压和电阻,下列说法正确的是 【 】 A. 只要将导体连入电路,电路中就有电流 B. 地球为什么只有人类文明一种现代文明?难道几亿年都不曾有过其他文明吗? msp430 定时器 连续计数模式在连续计数模式下能改初值吗?tar,试验起来感觉能改但改的效果不对呢.书上的意思不是很明确. 在并联电路中,有关电压和电流的说法正确的是A各支路两端电压相等,通过各支路的电流相等B各支路两端电压不一定相等,通过各支路的电流相等C各支路两端电压相等,通过各支路的电流不一定 英语翻译:不要关闭起安全作用的开关和传感器. 数字定时器设计基本要求:60分可以定时显示现在定时的时间高级要求:40分可以倒记时 怎样可以令生物柴油不容易燃烧 “智能传感器系统设计”这句话的英文翻译 清洁能源包括哪些 生物柴油在空气中燃烧的两种产物是 英语翻译The radial resolution of multiple echoes ( Rres ) means theresolution of detection distance by calculating minimuminterval time of between the 1st echo and the 2nd echo ( Tres ).radial resolution 清洁能源有哪些?氢能源算吗? 生物柴油完全燃烧的两种主要产物拜托了各位 生物柴油比传统石油比有什么特点? 使用绿色能源有哪些好处 被蚂蜂蜇了怎么办? 在野外作战时如果被有毒的昆虫蜇伤应用药物消毒,请问蒜汁对下面哪一种昆虫咬伤有疗效: 绿色能源有哪些 一个覆灭的文明和物种 地球人类.人类至今以经灭亡一万三千年了我们来到地球,为一个智慧文明的覆灭而深感遗憾,在整个人类文明的后期历史中 英语翻译Nowadays,the Sensor Webs represent a very effective solution to global earth observation [1]–[5].The term “SensorWeb”refers to a network of heterogeneous and spatially distributed sensors whose data can be real-time accessed through 关于此电路图中串联并联各电压电流之间的关系 1.我不太明白4个电阻之间的串并联关系,如何看出此图哪个电阻是并哪个电阻是串的方法? 2.r1上的电流900mA 9V和r2,r3,r4上的电流300mA,3V是怎么计 人类会是地球上从诞生到消失时间最短的物种吗?人类的文明才不过千年,为什么反映出的各类毁灭危机几乎全在与人类创造出的必然结果.人是不是不如猪啊? 当人类灭亡后,地球会变成什么样? 探究海洋文明与大河文明各有何特点 人类会是地球最完美的物种吗?未来的几百年人类数量还会增多N倍.地球物种总数未来100年减少1倍.大多是人为因素.我想知道人类未来是毁灭于自然天灾.还是自己呢? 汽车传感器英文怎么翻译? 海洋文明与大河文明的区别 霍尔效应传感器输出数字电压信号,当金属片进入磁隙中时,其输出的电压信号从____V变为___V;而当金属片离开磁隙时,输出电压信号从___V变为____V.难道这问题没有人知道? 地球灭亡后我们人类该怎么办? 探究海洋文明与大河文明的特点 电位计当角传感器怎么用啊,大概多大的电阻,得到的是电压信号嘛? “传感器在机器人领域的应用”的英文是什么? 与海洋文明相比,大河文明的突出特点是拜托各位大神与海洋文明相比,大河文明的突出特点是 A,形成了发达的农耕文明 B,工商业极为发达 C,发展更快,长期领先 D,创造了辉煌灿烂的文化 求汽车各传感器标准电压电阻1请问大家汽车的空气流量传感器和进气压力传感器,节气门位置传感器,曲轴位置传感器,凸轮轴位置传感器,用万能表测量它们的电压值和电阻值的正常范围是多 假如人类灭亡,地球会成为什么样? 海洋文明与大河文明 水温传感器的两根线和电脑是怎样连接的为什么阻值越小给电脑的信号电压就越小呢电阻和电压不是成反比的吗 12v蓄电池充电器的充电电压多少最佳 蜇人的小虫子家里从去年开始天花板上出现一些类似小蚂蚁的虫子,虫子屁股上有毒刺,一碰到人就蜇,然后起个红包,非常难受,现在每天用打杀虫剂,就从天花板上掉下好多,现在不知道用啥办法 将传感器输出地电阻值转化为电压值用什么啊 自制12V汽车电瓶充电器我有一个12V变压器容量100VA 频率50/60HZ 我想为我的汽车电瓶充电用 我的电瓶是12V 256A 54Ah(20h) 请问下我还需要什么元件和具体的连接步骤 请详细说明下 小弟在这先感谢
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn