MapReduce-MulitipleOutputs实现自己定义输出到多个文件夹

Hadoop多输出任务实践
本文介绍了一种利用Hadoop MapReduce实现多个输出路径的方法,通过案例演示如何处理不同前缀的数据并将其分别归类到对应的集合中。此外,还讨论了通过设置baseOutputPath来优化输出文件管理的技术细节。

输入源数据例子:

Source1-0001
Source2-0002
Source1-0003
Source2-0004
Source1-0005
Source2-0006
Source3-0007
Source3-0008
描写叙述:
  • Source1开头的数据属于集合A。
  • Source2开头的数据属于集合B;
  • Source3开头的数据即属于集合A,也属于集合B。

输出要求:

  • 完整保留集合A数据(包括Source1、Source3开头数据)
  • 完整保留集合B数据(包括Source2、Source3开头数据)

程序实现:

import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.MultipleOutputs;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.mahout.common.AbstractJob;

import com.yhd.common.util.HadoopUtil;

/**
 * AbstractJob 是mahout的Job模板,能够不使用该模板,
 * 实则的核心部分在于MultipleOutputs部分
 * 
 * @author ouyangyewei
 *
 */
public class TestMultipleOutputsJob extends AbstractJob {
    @Override
    public int run(String[] args) throws Exception {
        addInputOption();
        addOutputOption();
        
        Map<String, List<String>> parseArgs = parseArguments(args);
        if(parseArgs==null){
            return -1;
        }
        
        HadoopUtil.delete(getConf(), getOutputPath());
        
        Configuration conf = new Configuration();
        conf.setInt("mapred.reduce.tasks", 4);
        conf.set("mapred.job.queue.name", "pms");
        conf.set("mapred.child.java.opts", "-Xmx3072m");
        conf.set("mapreduce.reduce.shuffle.memory.limit.percent", "0.05");

        Job job = new Job(new Configuration(conf));
        job.setJobName("TestMultipleOutputsJob");
        job.setJarByClass(TestMultipleOutputsJob.class);
        job.setMapperClass(MultipleMapper.class);
        job.setNumReduceTasks(0);
        FileInputFormat.setInputPaths(job, this.getInputPath());
        FileOutputFormat.setOutputPath(job, this.getOutputPath());
        
        /** 输出文件格式将为:Source1-m-**** */
        MultipleOutputs.addNamedOutput(job, "Source1", TextOutputFormat.class, Text.class, Text.class);
        /** 输出文件格式将为:Source2-m-**** */
        MultipleOutputs.addNamedOutput(job, "Source2", TextOutputFormat.class, Text.class, Text.class);
        
        boolean suceeded = job.waitForCompletion(true);
        if(!suceeded) {
            return -1;
        }
        return 0;
    }
    
    /**
     * 
     * @author ouyangyewei
     *
     */
    public static class MultipleMapper extends Mapper<LongWritable, Text, Text, Text> {
        private MultipleOutputs<Text, Text> mos = null;

        @Override
        protected void setup(Context context
                             ) throws IOException, InterruptedException {
            mos = new MultipleOutputs<Text, Text>(context);
        }

        public void map(LongWritable key, Text value, Context context
                        ) throws IOException, InterruptedException {
            String line = value.toString();
            String[] tokenizer = line.split("-");

            if (tokenizer[0].equals("Source1")) {
                /** 集合A的数据 */
                mos.write("Source1", new Text(tokenizer[0]), tokenizer[1]);
            } else if (tokenizer[0].equals("Source2")) {
                /** 集合B的数据 */
                mos.write("Source2", new Text(tokenizer[0]), tokenizer[1]);
            }
            
            /** 集合A交集合B的数据 */
            if (tokenizer[0].equals("Source3")) {
                mos.write("Source1", new Text(tokenizer[0]), tokenizer[1]);
                mos.write("Source2", new Text(tokenizer[0]), tokenizer[1]);
            }
        }

        protected void cleanup(Context context
                               ) throws IOException, InterruptedException {
            mos.close();
        }
    }
    
    /**
     * @param args
     */
    public static void main(String[] args) {
        System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
            "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
        System.setProperty("javax.xml.parsers.SAXParserFactory", 
            "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
        
        TestMultipleOutputsJob instance = new TestMultipleOutputsJob();
        try {
            instance.run(args);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用hadoop jar命令调度执行jar包代码:
hadoop jar bigdata-datamining-1.0-user-trace-jar-with-dependencies.jar com.yhd.datamining.data.usertrack.offline.job.mapred.TestMultipleOutputsJob \
--input /user/pms/workspace/ouyangyewei/testMultipleOutputs \
--output /user/pms/workspace/ouyangyewei/testMultipleOutputs/output

程序执行以后,输出的结果:
[pms@yhd-jqhadoop39 /home/pms/workspace/ouyangyewei]
$hadoop fs -ls /user/pms/workspace/ouyangyewei/testMultipleOutputs/output
Found 4 items
-rw-r--r--   3 pms pms         65 2014-12-16 09:18 /user/pms/workspace/ouyangyewei/testMultipleOutputs/output/Source1-m-00000
-rw-r--r--   3 pms pms         65 2014-12-16 09:18 /user/pms/workspace/ouyangyewei/testMultipleOutputs/output/Source2-m-00000
-rw-r--r--   3 pms pms          0 2014-12-16 09:18 /user/pms/workspace/ouyangyewei/testMultipleOutputs/output/_SUCCESS
-rw-r--r--   3 pms pms          0 2014-12-16 09:18 /user/pms/workspace/ouyangyewei/testMultipleOutputs/output/part-m-00000

[pms@yhd-jqhadoop39 /home/pms/workspace/ouyangyewei]
$hadoop fs -cat /user/pms/workspace/ouyangyewei/testMultipleOutputs/output/Source1-m-00000
Source1	0001
Source1	0003
Source1	0005
Source3	0007
Source3	0008

[pms@yhd-jqhadoop39 /home/pms/workspace/ouyangyewei]
$hadoop fs -cat /user/pms/workspace/ouyangyewei/testMultipleOutputs/output/Source2-m-00000
Source2	0002
Source2	0004
Source2	0006
Source3	0007
Source3	0008


补充于2014-12-18:

这样的方式的缺陷是会产生非常多类似Source1或Source2开头的子文件,一种非常好的方式就是指定baseOutputPath,将Source1开头的文件放在同一个文件夹中管理

对上述代码进行改写实现文件夹管理:

public void map(LongWritable key, Text value, Context context
                        ) throws IOException, InterruptedException {
            String line = value.toString();
            String[] tokenizer = line.split("-");

            if (tokenizer[0].equals("Source1")) {
                /** 集合A的数据 */
                mos.write("Source1", 
                          new Text(tokenizer[0]), 
                          tokenizer[1],
                          "Source1/part");
            } else if (tokenizer[0].equals("Source2")) {
                /** 集合B的数据 */
                mos.write("Source2", 
                          new Text(tokenizer[0]), 
                          tokenizer[1],
                          "Source2/part");
            }
            
            /** 集合A交集合B的数据 */
            if (tokenizer[0].equals("Source3")) {
                mos.write("Source1", 
                          new Text(tokenizer[0]), 
                          tokenizer[1],
                          "Source1/part");
                
                mos.write("Source2", 
                          new Text(tokenizer[0]), 
                          tokenizer[1],
                          "Source2/part");
            }
        }
程序执行以后,输出的结果:
$hadoop fs -ls /user/pms/workspace/ouyangyewei/testUsertrack/job1Output
Found 4 items
-rw-r--r--   3 pms pms          0 2014-12-18 14:11 /user/pms/workspace/ouyangyewei/testUsertrack/job1Output/_SUCCESS
-rw-r--r--   3 pms pms          0 2014-12-18 14:11 /user/pms/workspace/ouyangyewei/testUsertrack/job1Output/part-r-00000
drwxr-xr-x   - pms pms          0 2014-12-18 14:11 /user/pms/workspace/ouyangyewei/testUsertrack/job1Output/Source1
drwxr-xr-x   - pms pms          0 2014-12-18 14:11 /user/pms/workspace/ouyangyewei/testUsertrack/job1Output/Source2

[pms@yhd-jqhadoop39 /home/pms/workspace/ouyangyewei/testUsertrack]
$hadoop fs -ls /user/pms/workspace/ouyangyewei/testUsertrack/job1Output/Source1
Found 1 items
-rw-r--r--   3 pms pms   65 2014-12-18 14:11 /user/pms/workspace/ouyangyewei/testUsertrack/job1Output/Source1/part-r-00000

[pms@yhd-jqhadoop39 /home/pms/workspace/ouyangyewei/testUsertrack]
$hadoop fs -ls /user/pms/workspace/ouyangyewei/testUsertrack/job1Output/Source2
Found 1 items
-rw-r--r--   3 pms pms   65 2014-12-18 14:11 /user/pms/workspace/ouyangyewei/testUsertrack/job1Output/Source2/part-r-00000

能够參考下:http://dirlt.com/mapred.html

转载于:https://www.cnblogs.com/yangykaifa/p/6773904.html

雪人计算机辅助翻译软件(Snowman Computer Assisted Translation Software——缩写为:雪人CAT)是一种充分利用计算机的超强计算能力、记忆能力和人的创造能力相结合的人机互动的辅助翻译软件,由译员把握翻译质量,计算机提供辅助。它能够辅助译员优质、高效、轻松地完成翻译工作,帮助企业及个人充分利用资源、降低成本、成倍提高工作效率。适用于需要精确翻译的机构和个人。   雪人CAT软件特色:1. 简单易用、速度快:瞬间完成在百万级的记忆库中整句匹配或片段搜索;2. 准确、快速的双语对齐句级对齐: 轻松创建大型记忆库。 3. 实时预览技术:译文预览随译随见;还支持预览原文和译文、原文混合预览。4. 自动替换翻译:雪人采用EBMT和TM两种技术相结合,实现自动替换翻译。5. 嵌入在线自动翻译和在线词典:自动给出“在线自动翻译”的译文供参考;嵌入“hotdic、naver、daum、hujiang、wenguo”等多个韩语在线词典,切换方便。6. 用户自定义语法规则翻译,进一步提高取词和翻译的效率。7. 质量检查功能:可以检查术语一致、数字校验、漏译、拼写、错别字、一句多译等等。 8. 预翻译:利用记忆库、词典、规则词典、本地术语库和在线翻译相结合等方式进行预翻译,快速生成译文。   雪人CAT韩语版既可以单独使用也也可以作为客户端接入雪人网络协同平台,通过协同翻译平台实现团队协同翻译。   “雪人CAT协同翻译平台”简化了服务器架设及对服务器系统的要求,无论是拥有专门的技术人员、高性能的服务器的大型企业,还是小型的翻译公司和翻译团队都可以轻松地架设雪人CAT协同翻译平台,使翻译企业、翻译团队拥有自主的协同翻译平台,切实保障翻译资料的安全、保密性。“雪人CAT协同翻译平台”由服务器端软件和客户端软件构成。不仅可以在Windows Server 2003/2008服务器版本的操作系统下使用,也可以在Windows XP及以上的操作系统下使用。   协同翻译平台:1. 服务器架设简单、响应速度快:软件下载解压后,双击服务器程序即完成服务器的架设;不限接入的用户数量,即使多用户同时访问,亦能快速响应。2. 实时共享记忆库:翻译的句子自动同步到服务器中,其他成员若遇到与之相似的句子时,立即提示给他。3. 实时共享术语库:项目组成员定义的术语,经审核后,其他成员均可使用。严格保证专业术语在同一项目或多个项目中的统一。4. 实现翻译与审校同步:在译员翻译的同时审校同步对翻译稿件进行审核,达到“一人问题、及时解决、全体收益”的目标。5. 整合即时通讯、文档管理、论坛于一体:高效率的沟通平台让团队整体能力得到充分的发挥,用团队的集体智慧解决问题,避免了个体解决问题的能力局限性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值