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

利用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处理二进制格式文件       (编辑/刘亚琼  审校/仲浩)

移动周报:疯狂吐槽还是更得欢心?细数iOS 7的是与非 国内最受欢迎的开源项目集锦 开始3D编程前需注意的十件事 [CTO俱乐部第100期]软件平台的新思维及2345技术团队管理经验分享 失败怪圈:今天的移动App在重蹈1999年的覆辙 极客编程必备的五大PHP开发应用 Oracle或将宣布与Salesforce.com,NetSuite以及微软结盟 【专访间】神州数码谢耘:智慧城市需要以“融合平台”为特征的沃尔玛模式 对话OW2 CEO:开源≠安全隐患,免费≠无利可图 不断抄袭的Facebook正逐步沦为一家普通的公司 Windows 8.1会不会把Windows 8的“Modern”开发者踢到路边 任志鹏:FusionCloud是华为二十年技术积累的精华 机器学习典范?iOS7中的Siri能主动学习如何发音 三星宣布关闭PC业务 主推便携设备和一体机 Web设计师必须掌握的六大设计策略 Facebook为什么要推Instagram视频分享功能? 天气预报(id后面的9位数字为城市代码)年月日,星期,当前时间(仅用于javascript) PHP 5.5.0发布 不再支持Windows XP和2003 专访ThinkPHP创始人刘晨:用最简单最快速的方式开发PHP应用 重构:仔细查看,改进代码 加速编码的17款最棒的CSS工具 生于微信:专访疯狂猜图CEO曹晓刚 谷歌:受感染的合法网站远比恶意网站危险性大 Mozilla正式发布Firefox 22应用程序开发者受益 支持3D游戏、视频通话和文件分享 直接拿来用!最火的前端开发项目(一) Salesforce.com和Oracle在云合作上达成长期协议 即将到来的数据中心僵尸末日,谁能成为最后的幸存者?! Andorid APK反逆向解决方案:梆梆加固原理探寻 科技拥抱设计:体验设计如何创新? Rails 4.0正式发布 命途多舛的webOS,两度易主,生生死死多少回 封装在Dll中的窗口焦点问题 为什么我用JBUILDER编译JSP文件,用web run执行后会出现这些情况?? 有谁用过CMPPE2.0协议开发过网关程序的请进 win2000下内存使用的问题? 我每次都结贴子的,不信你们查一下啊,这次再请帮忙,谢谢哦 在公共文件夹如公告窗体的原件与回复件是如何关联的? delphi中form中放了一副图,怎样让图可见而form不可见? 一个关于vba的应用问题?合并文档 英文版的vb中该如何来把一个项目进行打包呢(想把它安装到一台没有装vb 的电脑上) 删除多余的重复记录 如何获取屏幕尺寸? 有人用过EasyPack的仿真器吗? 关于QuickRpt报表存盘后出现乱码的问题。 邮件监测器要怎么写?? 关于Web Browser控件 如何加快蓝点linux的安装速度 access 表中的datetime型字段在delphi中如何使用? 《windows 网络编程技术》是哪个出版社的 小弟正学socket编程,有个问题请教! 微软专家请看: Sybase数据库中的中文存储问题! 连接池在TOMCAT中不可用吗?我是新人。 简单的问题? SOS!!!!!!!!高分赠送!!请教大虾们一个有关MSSQL一个问题!! 我在VB.NET下调用弹出对话框,可是无论click确定还是取消,结果都一样,我写的有什么错误吗? 紧急寻找?????????高分求助 关于dbgril的问题。简单的问题加分哦 为什么不能编译这个头文件? 寻bmp转gif代码 vb.net做的control能在基于c#的web form中使用吗? 白痴问题:使用java有什么好处? 在线:在程序中加载任一网页,用鼠标点击任一超连接,均能捕获所点击连接的文本。该如何做? 至今,我不明白为什么使用友元(friend)函数!(50分赠送) Access如何外连接多个表 给我一个直接访问DBF文件的控件,在线等待。。。 求一sql语句! 哪位有ORACLE的帮助文件,送50分! 怎样在ListView中实现换行功能 在PB使用Word 模板(.dot)将DW_1(FreeForm风格)转换成Word文件并追加DW_2(Grid)数据 怎样可以在鼠标事件发生时获得鼠标相对应屏幕的坐标? 我想写一个组件在页面下载后将IE的始终用UF8发送项去掉且重启IE? 在视图中动态生成一个非模态对话框后怎么来得到指向该对话框的指针呢?大家来讨论好吗? 怎么实现在多台客户机上接收一台主机的屏幕? 急!!!vc进程与vb进程间通讯的好办法 软件工程硕士!!!!!!!!!!!!! 如何批执行存储过程??? 求助!!! 快找工作了,兴奋加苦恼.来寻求一点安慰. 关于动态链库问题,虽然前讨论过。但都没有得出结果。再次请高手进。 请问与数据库的连接这段程序那里错了??? sql嵌入式编程 李老师带320元钱去买球,买了4个篮球以后,(一个篮球60元)剩下的钱正好买2个足球,一个足球是多少钱 关于的作文 400字 可以用数学证明 入射角等于反射角吗?如果能,感激不尽. 李老师带1000元去买球,买了四个篮球以后剩下的钱正好能买两个足球,一个足球的价钱是多少元?一个篮球的价钱是140元 作文在磨砺中成长700字学习题材 商店以每双6,5元购进批凉鞋,售价每双7,4元,卖到还剩5双时,除成本外还剩44元,这批凉鞋共几双 春游作文(300字)自己回答别复制! 作文:__我真的长大了 初中水平、600字以上(借鉴一下~) 以每双6.5元购进一批凉鞋,售价7.4元,卖到还剩5双时,除成本价还获胜利44元,有几双凉鞋 战胜困难的作文五百字 作文:我会学着长大(600字)如果是抄的,请说出出路!如果是抄的,却没说出出路者,无效! 如果你希望自己的朋友从原来的胆小懦弱变得勇敢坚强起来,你可以用这样一句名言来规劝他____________ 以战胜困难为题300字作文 关于寂寞的文章、 一个圆形环岛的直径是50m,中间是一个直径为10m的圆形草坪.小明以60米/分的速度绕行环岛一周大约需要多长时间?一年需要修剪草的总面积是多少? 求一个 背景是黄色的 一个女生 坐在椅子上 手放在桌子上的 头像背景是黄色的一个女生坐在椅子上手放在或搭在桌子上帮我找一下这个头像 圆形花坛周围是一条环形小路,花坛是直径4m,小路宽式2m,这条环形小路占地多少平方米? 圆形环岛的直径是20米,中间有一个半径是5米的花坛,其余地方是草坪.如果花坛的四周每隔2米栽一棵树,种一个圆形环岛的直径是20米,中间有一个半径是5米的花坛,其余地方是草坪。如果花 怎样在女同学睡觉的时候摸她的胸或屁股她却不会醒来?(睡觉时是坐在椅子上靠在桌子上的) 圆形花坛周围是一条环形小路,花坛的直径是10米,小路宽是2米,这条环形小路占地多少平方米?列式计算 一个圆形环岛的直径是20米,中间有一个半径是5米的花坛,其余部分是草坪.如果花坛的四周每隔2米栽一棵 李老师去商店买了8个足球和2个篮球足球的单价是篮球的3/4一共花去640元足球篮球单价各几元算式快还有一题妈妈买了8千克桃和12千克西瓜共花去48元已知2千克桃的钱相当于3千克西瓜的价钱 有什么动漫 里面的男主角一开始是一个非常胆小,懦弱的人 后来为了保护身边的人而变得勇敢,坚强.一定要看题.要日本动漫哦 ,剧情要好,有点H也不错,好吧.不要说妖怪之类的 人物也要美型. 某小区有一个长25米,宽20米的长方形游泳池,请你选择合适的比例尺,游泳池的长和宽分别画多少厘米?最好有计算过程 右图是某小学游泳池的平面图,这幅图的比例尺1:2000再计算出游泳池的长和宽各是几米?长2cm,宽3cm在线等快点今天就要拜托啦 如果你希望自己的朋友从原来的胆小懦弱变得勇敢坚强起来,你可以用这样的一句名言来规劝他-------------?刚才的人帮我想想啊! 以孤独为话题的 作文怎么写 选择.1.新世纪小学新建了一个长方形游泳池,长50m.宽30m.选用比例尺()画出的平面图最大;选用比例尺()画出的平面图最小.a.1:1000 b.1:1500 c.1:500 如果你希望自己的朋友胆小懦弱变得勇敢起来,你可以用哪句名言来劝他? 以寂寞为话题的作文, 一个圆形花坛的半径是4m,在他的周围修一条2m宽的小路,求小路的面积要画出示意图, 商店一每双6.50元购进一批凉鞋,售价为7.40元,卖到还剩下5双时,除成本外以获利44元,这批凉鞋共有多少双? 600字的野炊作文 600字 某小学有一个长60m,宽40m的游泳池,选用比例尺( )画出的平面图最大,选用比例尺( )画的平面图最小.A.1:2000 B.1:1500 C.1:1000 作文:对自己的期望300字左右今天开学老板让我们写“对自己的期望”300字左右今天六点之前写好! 关于春游 野炊的作文我们煮的是火锅哦!字数现在400字左右!马上就要! 一个圆形花坛的外面环绕一条小路,已知花坛周长是31.4m,小路的宽是2m,这条小路的面积是多少米?小路外圆的周长是多少米? 某商店以每双6.5元购进一批凉鞋,售价为7.4元,买到还剩5双时,除成本外还获得44元毛利.这批凉鞋共有多少双?(列方程解答) 作文《思念是一种美丽的孤独》 作文我不再孤独有什么开头是我今年13岁了,我有一个哥哥的 商店以每双6.5元购进一批凉鞋,售价每双7.4元买到还剩5双时,除成本外还赚44元,这批凉鞋共多少双?解方程应用题 信息世界的烦恼 作文(400字以下、350字以上)急、5月11日六点关闭问题(跪求) 我不再孤独 作文这是半命题作文..随便一篇我不再什么都可以啊! 一个圆形环岛的直径是20米,中间有一个半径是5米的花坛,其余地方是草坪. 有关寂寞的文章是议论文 作文《从此,我不再孤单》怎样写? 教室里有若干名学生,走了10个女生后,男生人数是女生人数的2倍;又走了9个男生后,女生是男生人数的2倍.那么最初有多少名女生? 小作文,有关寂寞的层次分析法模仿写作——运用具体细腻的语言表现某一种情绪或心情或体验或感悟.(300字左右) 我不再孤单 作文 教室中有若干名学生,走了10女生后,男生人数是女生人数2倍,又走了9个男生后,女生是男生的5倍,最初有女 春游的作文600字复制的不要来!复制的别来! 一个圆形花坛直径是10m,在花坛的周围铺一条2m宽的环形小路,路的面积是多少? 教室内有若干个学生,走了10名女生后,男生人数是女生人数的2倍,又走了6名男生后,女生人数是男生的2倍,教室最初有多少名女生? 战胜困难的300字作文 下图是中山小学游泳池的平面图,如果游泳池长50米,宽30米,量出所有需要的数据,求这幅图的比例尺.图上测量的:图是一个长方形也就是游泳池,长2.5,宽1.5. 商店以每双13元的价格购进了一批凉鞋,售价为每双14.8元,卖到还剩5双时,出去购进这皮凉鞋的费用还获利88元.问这批凉鞋共多少双? 战胜困难的作文300 商店以每双13元的进价购进一批凉鞋,售价14.8元,卖到还剩5双时,除去购进这批鞋子所用的钱外还获利88元.要算式、 商店以每双13元购进一批凉鞋,售价为14.8元,卖到还剩5双时,除去购进这批凉鞋的全部开销外还获利88元.问 我的烦恼作文200字
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘