//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. 巨蟒python全栈开发flask15项目开始7

    1.连续收取未读消息&&未读消息所属人 2.Pypinyin NLP中文同音字识别 3.jieba分词 4.Gemsim框架之LsiModel稀疏矩阵相似度 5.Gensim的应用 6 ...

  2. linux 将同后缀名的文件统一移至另一个文件夹

    w

  3. PHP file_get_contents和curl区别

    一.file_get_contents 1.定义 file_get_contents() 函数将指定 URL 的文件读入一个字符串并返回. 2.语法 file_get_contents(path, i ...

  4. 剑指Offer——机器人的运动范围

    题目描述: 地上有一个m行和n列的方格.一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子. 例如,当k为18时,机器人 ...

  5. Jumpserver使用

    堡垒机介绍 在一个特定网络环境下,为了保障网络和数据不受外界入侵和破坏,而运用各种技术手段实时收集和监控网络环境中每一个组成部分的系统状态.安全事件.网络活动,以便集中报警.及时处理及审计定责. 我们 ...

  6. Django源码安装方法及创建启动项目

    一.源码安装方法 下载源码包:https://www.djangoproject.com/download/ 输入以下命令并安装: tar xzvf Django-X.Y.tar.gz # 解压下载包 ...

  7. LightOJ1003---Drunk(拓扑排序判环)

    One of my friends is always drunk. So, sometimes I get a bit confused whether he is drunk or not. So ...

  8. Data striping

    条带化是把连续的数据分割成相同大小的数据块,把每段数据分别写入到阵列中的不同磁盘上的方法. 当多个进程同时访问一个磁盘时,可能会出现磁盘冲突.大多数磁盘系统都对访问次数(每秒的 I/O 操作,IOPS ...

  9. 理解Global interpreter lock

      Global interpreter lock (GIL) is a mechanism used in computer language interpreters to synchronize ...

  10. oracle查看被锁的表和被锁的进程,杀掉进程

    -- 1. 查看被锁的表 SELECT p.spid, a.serial#, c.object_name, b.session_id, b.oracle_username,b.os_user_name ...