本帖最后由 lzw 于 2013-12-3 21:49 编辑
在Mapreduce 的程序设计中,有时候会遇到多文件输出的使用。job 定义的FileOutputFormat 默认只有一个输出,如果是多机实现,该目录下包含多个类似part-000xx 的文件。在mapreduce中一个reducer对一个recordwriter,recordwriter只负责最后数据的写入,因此文件的个数与job指定的reduce个数一致。
但是我们需要多文件输出怎么处理,目前总结为两种方法:
第一种方法:使用MultipleOutputFormat
MultipleOutputFormat 只是一个抽象的类,MultipleTextOutputFormat 和MultpleSequenceFileOutputFormat 是它的两个具体实现。顾名思义,MultipleTextOutputFormat 的多个文件输出都是TextOutputFormat,即一行一对的文本格式,而MultpleSequenceFileOutputFormat 的多个文件输出都是SequenceFile,即二进制文件格式。
具体实现方法如下:
实现方式可以直接继承MultipleOutputFormat 抽象累,也可直接继承MultipleTextOutputFormat类重写generateFileNameForKeyValue方法,如果输出文件为二进制格式则直接继承MultpleSequenceFileOutputFormat 类。我这里输出为text格式,所以直接继承MultipleTextOutputFormat类,代码如下:
- static class MyMultipleOutputFormat extends MultipleTextOutputFormat<Text, Text>{
-
- @Override
- protected String generateFileNameForKeyValue(Text key,Text value,String name){
- // 相同key值的放在同一个文件夹下
- return new Path(key.toString(), name).toString();
-
- }
复制代码
最后在jobconfig中配置输出格式:- JobConf job = new JobConf();
- // 设置输出格式。
- job.setOutputFormat(MyMultipleOutputFormat.class);
复制代码
这种方式实现其实是通过实现输出文件指定目录,如果直接按照key输出在同一个文件,则generateFileNameForKeyValue 返回值直接修改为return key。
第二种方式:使用MultipleOutputs
MultipleOutputs 是在job 指定的output 输出的基础上,新增加一些额外的输出,与MulitpleOutputFormat 相比,它才是真正意义上的多文件输出。分两种情况:
附加单个输出文件,调用MultipleOutputs 的addNamedOutput 方法, 则是添加一个附加文件OutputFormat 格式及key, value 类型都可以自定义;代码实现如下:- JobConf job = new JobConf();
-
- MultipleOutputs.addNamedOutput(job, "myfile", TextOutputFormat.class, NullWritable.class, Text.class);
复制代码
另一种方式是多个文件输出,在reduce阶段增加一些输出:- <blockquote>public static class Reduce extends Reducer<Text,Text,Text,Text>{
复制代码
上面是我最近总结的两种方式,大家还有其它方式没有,可以跟帖分享一下。
加入qq群(号码:39327136),讨论云技术,获取最新资讯资源等
|