OutputFormat概述

OutputFormat主要是用来指定MR程序的最终的输出数据格式 。

默认使用的是TextOutputFormat,默认是将数据一行写一条数据,并且把数据放到指定的输出目录下,以 part-r-xxxxx数字开头。并且默认情况下有几个ReduceTask就有几个结果文件产生

自定义OutputFormat

自定义OutputFormat的详细流程:

  1. 定义MyOutputFormat继承FileOutputFormat<T>,泛型传入的是Reducer的输出类型
  2. 重写里面的getRecordWriter()方法,这个方法需要返回一个RecordWriter对象。

    这个方法里面定义了最终文件输出到什么地方

  3. 创建一个RecordWriter对象,继承RecordWriter<T>,重写里面的两个方法:write()、close()。其中write()方法中需要定义想要将文件输出到什么地方去,在这个方法中定义输出数据地址和输出数据格式
  4. 在Driver中通过job.setOutputFormatClass()指定我们使用的是哪个OutputFormat实现类

注意】如果设置了分区,并且指定了ReduceTask的数量,那么根据以前所学的有多少个ReduceTask就会生成多少个结果文件,是因为默认使用的是TextOutputFormat实现类,这个实现类就是几个ReduceTask就有几个结果文件。但是如果我们自定义了OutputFormat,那么结果文件只有我们指明的地址,没有其他。

案例实操

案例一:存储数据到MySQL中

需求:将手机流量数据根据总流向升序输出到MySQL数据库中

代码:

  1. FlowOutputInformat.java

    public class FlowOutputFormat extends FileOutputFormat<FlowBean, NullWritable> {
    @Override
    public RecordWriter<FlowBean, NullWritable> getRecordWriter(TaskAttemptContext taskAttemptContext) throws IOException, InterruptedException {
    return new MyRecordWriter();
    }
    }
  2. MyRecordWriter.java

    public class MyRecordWriter extends RecordWriter<FlowBean, NullWritable> {
    /**
    * 需要在这个方法中定义输出格式、输出数据地址
    * @param flowBean:Reduce阶段输出数据Key值
    * @param nullWritable:Reduce阶段输出value值
    */
    @SneakyThrows
    @Override
    public void write(FlowBean flowBean, NullWritable nullWritable) throws IOException, InterruptedException {
    Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/sx_bigdata?serverTimezone=UTC", "root", "root");
    PreparedStatement preparedStatement = connection.prepareStatement("insert into phone_flow values (?, ?, ?, ?)");
    preparedStatement.setString(1, flowBean.getPhone());
    preparedStatement.setInt(2, flowBean.getUpFlow());
    preparedStatement.setInt(3, flowBean.getDownFlow());
    preparedStatement.setInt(4, flowBean.getSumFlow());
    int i = preparedStatement.executeUpdate();
    if (i > 0) {
    System.out.println("添加成功!");
    } else {
    System.out.println("添加失败!");
    }
    connection.close();
    preparedStatement.close();
    } @Override
    public void close(TaskAttemptContext taskAttemptContext) throws IOException, InterruptedException { }
  3. FlowDriver.java

    job.setOutputFormatClass(FlowOutputFormat.class);

案例二:存储数据到HDFS本地指定文件夹中

需求:将单词计数案例结果输出到本地,其中首字母为大写字母存储在/upper.txt目录下,首字母为小写字母存储在/lower.txt目录下

代码:

  1. MyOutputFormat.java

    public class MyOutputFormat extends FileOutputFormat<Text, LongWritable> {
    @SneakyThrows
    @Override
    public RecordWriter getRecordWriter(TaskAttemptContext taskAttemptContext) throws IOException, InterruptedException {
    return new MyRecordWriter(taskAttemptContext);
    }
    }
  2. MyRecordWriter.java

    public class MyRecordWriter extends RecordWriter<Text, LongWritable> {
    FSDataOutputStream fsDataOutputStream1;
    FSDataOutputStream fsDataOutputStream2;
    public MyRecordWriter(TaskAttemptContext taskAttemptContext) throws Exception {
    Configuration configuration = taskAttemptContext.getConfiguration();
    FileSystem fs = FileSystem.get(new URI("hdfs://192.168.218.55:9000"), configuration, "root");
    Path out1 = new Path("/test/school/upper.txt");
    Path out2 = new Path("/test/school/lower.txt");
    if (fs.exists(out1)) {
    fs.delete(out1, true);
    }
    if (fs.exists(out2)) {
    fs.delete(out2, true);
    }
    fsDataOutputStream1 = fs.create(out1);
    fsDataOutputStream2 = fs.create(out2);
    } @Override
    public void write(Text text, LongWritable longWritable) throws IOException, InterruptedException {
    char firstWord = text.toString().charAt(0);
    String line = text + "\t" + longWritable.get() + "\r\n";
    if (Character.isUpperCase(firstWord)) {
    fsDataOutputStream1.write(line.getBytes());
    } else {
    fsDataOutputStream2.write(line.getBytes());
    }
    } @Override
    public void close(TaskAttemptContext taskAttemptContext) throws IOException, InterruptedException {
    if (fsDataOutputStream1 != null) {
    fsDataOutputStream1.close();
    }
    if (fsDataOutputStream2 != null) {
    fsDataOutputStream2.close();
    }
    }
    }
  3. FlowDriver.java

    job.setOutputFormatClass(MyOutputFormat.class);

MapReduce框架原理-OutputFormat工作原理的更多相关文章

  1. MapReduce作业的工作原理

    在Hadoop中,我们可以通过Job对象的submit()方法来运行MapReduce作业,也可以调用waitForCompletion()用于提交以前没有提交过的作业,并等待它的完成.其中,subm ...

  2. Hadoop(20)-MapReduce框架原理-OutputFormat

    1.outputFormat接口实现类 2.自定义outputFormat 步骤: 1). 定义一个类继承FileOutputFormat 2). 定义一个类继承RecordWrite,重写write ...

  3. MapReduce框架原理-MapTask工作机制

    MapReduce框架原理-MapTask工作机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. maptask的并行度决定map阶段的任务处理并发度,进而影响到整个job的处理速 ...

  4. MapReduce的工作原理

    MapReduce简介 MapReduce是一种并行可扩展计算模型,并且有较好的容错性,主要解决海量离线数据的批处理.实现下面目标 ★ 易于编程 ★ 良好的扩展性 ★ 高容错性   MapReduce ...

  5. MapReduce 1工作原理图文详解

    MapReduce工作原理图文详解 一 MapReduce程序执行流程 程序执行流程图如下: 流程分析:1.在客户端启动一个作业.2.向JobTracker请求一个Job ID.3.将运行作业所需要的 ...

  6. MapReduce工作原理详解

    文章概览: 1.MapReduce简介 2.MapReduce有哪些角色?各自的作用是什么? 3.MapReduce程序执行流程 4.MapReduce工作原理 5.MapReduce中Shuffle ...

  7. MapReduce工作原理图文详解

    目录:1.MapReduce作业运行流程2.Map.Reduce任务中Shuffle和排序的过程 1.MapReduce作业运行流程 流程示意图: 流程分析: 1.在客户端启动一个作业. 2.向Job ...

  8. MapReduce工作原理讲解

    第一部分:MapReduce工作原理 MapReduce 角色•Client :作业提交发起者.•JobTracker: 初始化作业,分配作业,与TaskTracker通信,协调整个作业.•TaskT ...

  9. MapReduce工作原理

    第一部分:MapReduce工作原理   MapReduce 角色•Client :作业提交发起者.•JobTracker: 初始化作业,分配作业,与TaskTracker通信,协调整个作业.•Tas ...

随机推荐

  1. 8、inotify和resync的优缺点

    只有对外提供访问的服务需要有端口号,本地服务无端口号: 8.1.inotify的优缺点: 1.优点: 监控文件系统事件变化,通过同步工具实现实时的数据同步 2.缺点: 并发如果大于200个文件(10- ...

  2. linux设备驱动编写入门

    linux设备驱动是什么,我个人的理解是liunx有用户态和内核态,用户空间中是不能直接对设备的外设进行使用而内核态中却可以,这时我们需要在内核空间中将需要的外设驱动起来供用户空间使用.linux的驱 ...

  3. python导入模块--案例

    1 导入模块 1.1 问题 本案例要求先编写一个star模块,主要要求如下: 建立工作目录 ~/bin/ 创建模块文件 ~/bin/star.py 模块中创建pstar函数,实现打印50个星号的功能 ...

  4. Linux date 获取时间

    获取当前日期: ubuser@ubuser-OptiPlex-7010:~$ date +%Y_%m_%d2020_12_16 获取当前时间: ubuser@ubuser-OptiPlex-7010: ...

  5. Swoole实现毫秒级定时任务

    项目开发中,如果有定时任务的业务要求,我们会使用linux的crontab来解决,但是它的最小粒度是分钟级别,如果要求粒度是秒级别的,甚至毫秒级别的,crontab就无法满足,值得庆幸的是swoole ...

  6. 转:nginx服务器配置

    1. user www-data说明的是使用的用户,至于www-data这个用户是系统自带的,我们不用说系统里没有这个账户的,虽然这个账户具体是做什么的,我也不太清楚2.worker_processe ...

  7. B站蹦了,关我A站什么事?

    昨天的大瓜,B站蹦了,大伙都跳起来分析了一波异常原因,着实给大伙的秋招准备了一波热乎乎的素材!在大家都在关注 B站的时候, 我大A站终于要站起来了!!!经过多方网友的极力引流,我A站也蹦了- 紧急通知 ...

  8. android实现计时器(转)

    新建布局文件activity_main.xml   <?xml version="1.0" encoding="utf-8"?> <Linea ...

  9. 《手把手教你》系列技巧篇(八)-java+ selenium自动化测试-元素定位大法之By id(详细教程)

    1.简介 从这篇文章开始,要介绍web自动化核心的内容,也是最困难的部分了,就是:定位元素,并去对定位到的元素进行一系列相关的操作.想要对元素进行操作,第一步,也是最重要的一步,就是要找到这个元素,如 ...

  10. hadoop源码_hdfs启动流程_2_DataNode

    执行start-dfs.sh脚本后,集群是如何启动的? 本文阅读并注释了start-dfs脚本,以及datanode的启动主要流程流程源码. DataNode 启动流程 脚本代码分析 start-df ...