//MultipleOutputs类用于简化多文件输出
The MultipleOutputs class simplifies writing output data to multiple outputs

//案例一:在job默认的输出之外,附加自定义的输出.自定义的输出可以指定:输出格式以及 key/value 类型.
Case one: writing to additional outputs other than the job default output. Each additional output, or named output, may be configured with its own OutputFormat, with its own key class and with its own value class.

//案例二:将不同的数据写到不同的文件中
Case two: to write data to different files provided by user

//MultipleOutputs支持计数器,默认是不启用状态.计数器组名是MultipleOutputs类的名字.计数器名字是自定义输出的名字.将记录个数写入对应的计数器.
MultipleOutputs supports counters, by default they are disabled. The counters group is the MultipleOutputs class name. The names of the counters are the same as the output name. These count the number records written to each output name.

//Job配置模板
Usage pattern for job submission: Job job = new Job(); FileInputFormat.setInputPath(job, inDir);
FileOutputFormat.setOutputPath(job, outDir); job.setMapperClass(MOMap.class);
job.setReducerClass(MOReduce.class);
... //定义TextOutputFormat格式的'text'输出
MultipleOutputs.addNamedOutput(job, "text", TextOutputFormat.class,
LongWritable.class, Text.class); //定义SequenceFileOutputFormat格式的'seq'输出
MultipleOutputs.addNamedOutput(job, "seq",
SequenceFileOutputFormat.class,
LongWritable.class, Text.class);
... job.waitForCompletion(true);
...
//reduce中使用
Usage in Reducer: String generateFileName(K k, V v) {
return k.toString() + "_" + v.toString();
} public class MOReduce extends
Reducer<WritableComparable, Writable,WritableComparable, Writable> { //1. 定义MultipleOutputs类型变量
private MultipleOutputs mos;

public void setup(Context context) {
...
//2. setup()方法对其初始化
mos = new MultipleOutputs(context);
} public void reduce(WritableComparable key, Iterator<Writable> values,
Context context)
throws IOException {
...
mos.write("text", , key, new Text("Hello"));

//3. reduce()方法中使用MultipleOutputs类的write方法输出 /**
*参数列表
* @ 自定义的输出名
* @ 输出的key
* @ 输出的value
* @ 输出的基础路径
*/
mos.write("seq", LongWritable(1), new Text("Bye"), "seq_a");
mos.write("seq", LongWritable(2), key, new Text("Chau"), "seq_b");
mos.write(key, new Text("value"), generateFileName(key, new Text("value")));
...
} public void cleanup(Context) throws IOException { //4. 关闭MultipleOutputs输出流
mos.close();
...
}
}

When used in conjuction with org.apache.hadoop.mapreduce.lib.output.LazyOutputFormat, MultipleOutputs can mimic the behaviour of MultipleTextOutputFormat and MultipleSequenceFileOutputFormat from the old Hadoop API - ie, output can be written from the Reducer to more than one location.

//使用以下方法可以不用指定自定义输出
Use MultipleOutputs.write(KEYOUT key, VALUEOUT value, String baseOutputPath) to write key and value to a path specified by baseOutputPath, with no need to specify a named output:

//定义变量
private MultipleOutputs out; public void setup(Context context) {
//初始化变量
out = new MultipleOutputs(context);
...
} public void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException {
for (Text t : values) {

//调用类中的Write()方法
/**
*参数列表
* @ 输出的key
* @ 输出的value
* @ 指定输出的基础路径
*/
out.write(key, t, generateFileName(<parameter list...>));
}
} protected void cleanup(Context context) throws IOException, InterruptedException {

//关闭输出流
out.close();
}
//自定义的生成基础路径的方法,即符号"/"有无的区别 Use your own code in generateFileName() to create a custom path to your results. '/' characters in baseOutputPath will be translated into directory levels in your file system. Also, append your custom-generated path with "part" or similar, otherwise your output will be -00000, -00001 etc. No call to context.write() is necessary. See example generateFileName() code below. private String generateFileName(Text k) {
// expect Text k in format "Surname|Forename"
String[] kStr = k.toString().split("\\|"); String sName = kStr[0];
String fName = kStr[1]; // example for k = Smith|John
// output written to /user/hadoop/path/to/output/Smith/John-r-00000 (etc)
return sName + "/" + fName;
}

//以上使用MultipleOutputs类的方法方式都会产生一个空的默认的【part-*-00000】的文件.
//在Job的配置中使用 LazyOutputFormat.setOutputFormatClass(job, TextOutputFormat.class);
//代替
job.setOutputFormatClass(TextOutputFormat.class);
//可以避免差生【part-*-00000】这一空文件
Using MultipleOutputs in this way will still create zero-sized default output, eg part-00000. To prevent this use LazyOutputFormat.setOutputFormatClass(job, TextOutputFormat.class); instead of job.setOutputFormatClass(TextOutputFormat.class); in your Hadoop job configuration.

总结:MR案例:多文件输出MultipleOutputs

  • 使用指定 自定义输出 的write方法,需要在Job配置中添加 MultipleOutputs.addNamedOutput(Job job, String namedOutput, Class<? extends OutputFormat> outputFormatClass, Class<?> keyClass, Class<?> valueClass);方法
  • 对于不使用指定 自定义输出 的write方法则不需要
  • Job结果中不再产生默认的空文件【part-*-00000】需要在配置中使用 LazyOutputFormat.setOutputFormatClass(job, TextOutputFormat.class);

解读:MultipleOutputs类的更多相关文章

  1. 【java源码】解读HashTable类背后的实现细节

    HashTable这个类实现了哈希表从key映射到value的数据结构形式.任何非null的对象都可以作为key或者value. 要在hashtable中存储和检索对象,作为key的对象必须实现has ...

  2. 详细解读LruCache类

    LruCache是android提供的一个缓存工具类,其算法是最近最少使用算法.它把最近使用的对象用“强引用”存储在LinkedHashMap中,并且把最近最少使用的对象在缓存值达到预设定值之前就从内 ...

  3. 逐步解读String类(一)

    一句题外话 面试刚入行的Java新手,侧重基础知识:面试有多年工作经验的老鸟,多侧重对具体问题的解决策略. 从一类面试题说起 考察刚入行菜鸟对基础知识的掌握程度,面试官提出关于String类的内容挺常 ...

  4. MR案例:多文件输出MultipleOutputs

    问题描述:现有 ip-to-hosts.txt 数据文件,文件中每行数据有两个字段:分别是ip地址和该ip地址对应的国家,以'\t'分隔.要求汇总不同国家的IP数,并以国家名为文件名将其输出.解读:M ...

  5. 通过MultipleOutputs写到多个文件

    MultipleOutputs 类可以将数据写到多个文件,这些文件的名称源于输出的键和值或者任意字符串.这允许每个 reducer(或者只有 map 作业的 mapper)创建多个文件. 采用name ...

  6. MapReduce 规划 六系列 MultipleOutputs采用

    在前面的示例,输出文件名是默认: _logs part-r-00001 part-r-00003 part-r-00005 part-r-00007 part-r-00009 part-r-00011 ...

  7. hadoop多文件输出MultipleOutputFormat和MultipleOutputs

    1.MultipleOutputFormat可以将相似的记录输出到相同的数据集.在写每条记录之前,MultipleOutputFormat将调用generateFileNameForKeyValue方 ...

  8. 详细解读Volley(三)—— ImageLoader & NetworkImageView

    ImageLoader是一个加载网络图片的封装类,其内部还是由ImageRequest来实现的.但因为源码中没有提供磁盘缓存的设置,所以咱们还需要去源码中进行修改,让我们可以更加自如的设定是否进行磁盘 ...

  9. 使用MultipleInputs和MultipleOutputs

    还是计算矩阵的乘积,待计算的表达式如下: S=F*[B+mu(u+s+b+d)] 其中,矩阵B.u.s.d分别存放在名称对应的SequenceFile文件中. 1)我们想分别读取这些文件(放在不同的文 ...

随机推荐

  1. 将工程导入到SVN仓库

    1.在桌面右键点开Tortoise客户端 2.选择仓库 3.在仓库的trunk目录下为新工程创建文件夹

  2. 离线微博工具Open Live Writer(Windows Live Writer)安装过程及server error 500错误解决

    必备条件: .net framework 3.5框架(大概是要求3.5或以上,不确定,好像没有人遇到和这个相关的问题) 2017年7月27日最新官方版0.6.2英文离线客户端网盘下载(官网的安装包无法 ...

  3. protobuf在java应用中通过反射动态创建对象(DynamicMessage)

    ---恢复内容开始--- 最近编写一个游戏用到protobuf数据格式进行前后台传输,苦于protobuf接受客户端的数据时是需要数据类型的如xxx.parseForm(...),这样就要求服务器在接 ...

  4. 2017 Multi-University Training Contest - Team 1—HDU6035

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:一棵树有n个点,每个点有自己的颜色,任意两个不同的点可以组成一条路径.也就是说一共有n(n ...

  5. [iOS微博项目 - 3.5] - 封装业务

    github: https://github.com/hellovoidworld/HVWWeibo   A.封装微博业务 1.需求 把微博相关业务(读取.写微博) 界面控制器不需要知道微博操作细节( ...

  6. ArcEngine之Provide your license server administrator with the following information.error code =-42

    今天打开VS,不一会就出现了下面的对话框,感到非常疑惑,仔细一想,原来是昨天不小心把权限弄错了! 解决办法:在控价中找到AxLicenseControl,右键属性,把权限改为ArcGIS Engine ...

  7. 用于金融分析的Python包

    1. NumPy:实现各种数组对象函数和傅立叶变换等等科学计算模块.2. SciPy:提供更多科学计算功能,包括矩阵,求解线性方程组,积分运算,优化等.3. matplotlib:一个跨平台的数值绘图 ...

  8. react 将字符串解析为markdown

    react 中有许多组件支持把字符串转化为markdown,并以html的形式展示出来.这里我试用了 react-markdown 和 hyperdown 两个库,发现hyperdown比较好,因为r ...

  9. openresty跑定时任务配置、ngx.timer.every接口使用

    openresty的定时任务是要跟worker绑定的.如果不绑定特定的worker,那么所有启动的woker都会去执行定时任务. 一般情况下默认绑定worker_id=0的,这样在nginx整个进程里 ...

  10. RESTful HTTP的实践(转)

    add by zhj: 文章有点老了,2009年的,到现在已经六年了,不过还是很有参考价值的. 另外,吐槽一下PUT method,竟然允许用户用实例号来创建,靠,这也行,实例号还是后台来定义比较方便 ...