当前位置: 首页 > news >正文

Hadoop3教程(十六):MapReduce中的OutputFormat

文章目录

  • (105)OutputFormat概述
  • (106)自定义OutputFormat案例需求分析
  • (107/108)自定义OutputFormat案例实现
    • 自定义Mapper
    • 自定义Reducer
    • 自定义OutputFormat
    • Driver
  • 参考文献

(105)OutputFormat概述

我们之前讲过了Map阶段的InputFormat,对应的,Reduce阶段也有自己的OutputFormat。

Reducer在执行完reduce()之后,接下来就会通过OutputFormat来将处理结果输出至外界环境。

Hadoop里默认使用的是TextOutputFormat,即将reduce()的处理结果,按行输出到文件。

而OutputFormat是MapReduce输出的基类,所有实现了MR输出的程序,都必须实现OutputFormat接口。

OutputFormat有几种官方自带的实现类(具体功能就不展开了):

  • NullOutputFormat
  • FileOutputFormat
    • MapFileOutputFormat
    • SequenceFileOutputFormat
    • TextOutputFormat(默认)
  • FilterOutputFormat
    • LazyOutputFormat
  • DBOutputFormat

OutputFormat类的核心方法:public abstract RecordWriter<K,V> getRecordWriter(...)

最终结果怎么写,以什么形式写,写到哪儿,等等这些,都是在getRecordWriter()里控制的。

当然,这些自带的实现类在日常的生产中肯定是不足以满足各种情况的,所以多数情况下,我们会实现自定义的OutputFormat类

自定义OutputFormat实现类需要:

  • 继承FileOutputFormat;
  • 改写RecordWriter,具体改写输出数据的方法write()

(106)自定义OutputFormat案例需求分析

需求:输入是一个日志文件,即log.txt,里面是罗列了一些访问过的网站,现在需要把其中包含atguigu的网站输出到a.log,不包含atguigu的网站输出到b.log。

输入数据形如:

http://www.baidu.com
http://www.atguibu.com
...

我们需要自定义一个OutputFormat类,即创建一个类LogRecordWriter继承RecordWriter,然后创建两个文件输出流,一个是atguiguOut,一个是otherOut。如果输入数据包含atguigu,就输出到atguiguOut,反之则输出到otherOut流。

最后还需要在驱动类里注册一下:

job.setOutputFormatClass(LogOutputFormat.class);

附注:

其实这个需求从直观上来讲,是可以通过分区来实现类似功能的,但是很遗憾,分区的话无法控制输出文件的名字,所以没法严格符合需求。

(107/108)自定义OutputFormat案例实现

这里直接复制了教程里的代码,来介绍一下,如何针对上一小节提出的需求,自定义OutputFormat。

自定义Mapper

首先需要创建一个自定义的Mapper类,如class LogMapper extends Mapper<LongWritable, Text, Text, NullWritable>

package com.atguigu.mapreduce.outputformat;import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;import java.io.IOException;public class LogMapper extends Mapper<LongWritable, Text,Text, NullWritable> {@Overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {//不做任何处理,直接写出一行log数据context.write(value,NullWritable.get());}
}

自定义Reducer

然后新建一个自定义Reducer类:

package com.atguigu.mapreduce.outputformat;import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;import java.io.IOException;public class LogReducer extends Reducer<Text, NullWritable,Text, NullWritable> {@Overrideprotected void reduce(Text key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException {// 防止有相同的数据,迭代写出for (NullWritable value : values) {context.write(key,NullWritable.get());}}
}

自定义OutputFormat

这里是最重要的一步,就是自定义一个OutputFormat类,继承RecordWriter:

  • 创建两个文件的输出流:atguiguOut、otherOut;
  • 如果输入数据中含有atguigu,则输出至atguiguOut,反之则输出到otherOut;

首先自定义OutputFormat类,重写RecordWriter方法,将我们自定义的LogRecordWriter放进去。

package com.atguigu.mapreduce.outputformat;import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.RecordWriter;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;import java.io.IOException;public class LogOutputFormat extends FileOutputFormat<Text, NullWritable> {@Overridepublic RecordWriter<Text, NullWritable> getRecordWriter(TaskAttemptContext job) throws IOException, InterruptedException {//创建一个自定义的RecordWriter返回LogRecordWriter logRecordWriter = new LogRecordWriter(job);return logRecordWriter;}
}

然后编写LogRecordWriter类,:

package com.atguigu.mapreduce.outputformat;import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.RecordWriter;
import org.apache.hadoop.mapreduce.TaskAttemptContext;import java.io.IOException;public class LogRecordWriter extends RecordWriter<Text, NullWritable> {private FSDataOutputStream atguiguOut;private FSDataOutputStream otherOut;public LogRecordWriter(TaskAttemptContext job) {try {//获取文件系统对象FileSystem fs = FileSystem.get(job.getConfiguration());//用文件系统对象创建两个输出流对应不同的目录atguiguOut = fs.create(new Path("d:/hadoop/atguigu.log"));otherOut = fs.create(new Path("d:/hadoop/other.log"));} catch (IOException e) {e.printStackTrace();}}@Overridepublic void write(Text key, NullWritable value) throws IOException, InterruptedException {String log = key.toString();//根据一行的log数据是否包含atguigu,判断两条输出流输出的内容if (log.contains("atguigu")) {atguiguOut.writeBytes(log + "\n");} else {otherOut.writeBytes(log + "\n");}}@Overridepublic void close(TaskAttemptContext context) throws IOException, InterruptedException {//关流IOUtils.closeStream(atguiguOut);IOUtils.closeStream(otherOut);}
}

Driver

最后编写LogDriver驱动类,把我们前面自定义的的类统统在驱动类里注册上:

package com.atguigu.mapreduce.outputformat;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;import java.io.IOException;public class LogDriver {public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {Configuration conf = new Configuration();Job job = Job.getInstance(conf);job.setJarByClass(LogDriver.class);job.setMapperClass(LogMapper.class);job.setReducerClass(LogReducer.class);job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(NullWritable.class);job.setOutputKeyClass(Text.class);job.setOutputValueClass(NullWritable.class);//设置自定义的outputformatjob.setOutputFormatClass(LogOutputFormat.class);FileInputFormat.setInputPaths(job, new Path("D:\\input"));//虽然我们自定义了outputformat,但是因为我们的outputformat继承自fileoutputformat//而fileoutputformat要输出一个_SUCCESS文件,所以在这还得指定一个输出目录FileOutputFormat.setOutputPath(job, new Path("D:\\logoutput"));boolean b = job.waitForCompletion(true);System.exit(b ? 0 : 1);}
}

至此需求完成。

参考文献

  1. 【尚硅谷大数据Hadoop教程,hadoop3.x搭建到集群调优,百万播放】

相关文章:

Hadoop3教程(十六):MapReduce中的OutputFormat

文章目录 &#xff08;105&#xff09;OutputFormat概述&#xff08;106&#xff09;自定义OutputFormat案例需求分析&#xff08;107/108&#xff09;自定义OutputFormat案例实现自定义Mapper自定义Reducer自定义OutputFormatDriver 参考文献 &#xff08;105&#xff09;Outp…...

通过表查询 sm37 排程运行情况 JOB 数据保存在表TBTCP 和 TBTCO中

sm36 设置排程 sm37 查看排程 se11 查表 Values for TBTCO-STATUS: A - Cancelled F - Completed P - Scheduled R - Active S - Released JOB 数据保存在表TBTCP 和 TBTCO中 参考 https://blog.51cto.com/u_15680210/5757746?articleABtest0 https://answers.sap.co…...

append_ocr_trainf

read_image (Image, D:/图像文件/字符识别/1-1.bmp) access_channel (Image, Image1, 1) * draw_rectangle2 (3600, Row, Column, Phi, Length1, Length2) gen_rectangle2 (Rectangle, 96.0436, 715.9526, 0.0173917050943654, 110.186941, 18.041084) reduce_domain (Image1, …...

小程序原生代码转uniapp

写了一份小程序原生代码&#xff0c;想转为uniapp 再转为其他平台发布 1、在命令行里&#xff0c;运行【 npm install miniprogram-to-uniapp -g 】进行安装&#xff0c;因为这个包是工具&#xff0c;要求全局都能使用&#x…...

云原生微服务 第五章 Spring Cloud Netflix Eureka集成负载均衡组件Ribbon

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 文章目录 系列文章目录[TOC](文章目录) 前言1、负载均衡1.1、服务端负载均衡1.2、…...

七大排序 (9000字详解直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序)

一&#xff1a;排序的概念及引入 1.1 排序的概念 1.1 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在…...

一、nginx配置

一、nginx配置 配置简介 1&#xff09;nginx相关目录 工作目录&#xff1a;/etc/nginx 执行文件&#xff1a;/usr/sbin/nginx 日志目录&#xff1a;/var/log/nginx 启动文件&#xff1a;/etc/init.d/nginx web目录&#xff1a;/var/www/html/&#xff0c;首页文件是index.ng…...

win32汇编-LEA指令是将一个内存地址加载到一个寄存器中

LEA (Load Effective Address) 指令是用来将一个内存地址加载到一个寄存器中的指令。 其语法为&#xff1a; lea destination, source 其中&#xff0c;destination 是目标寄存器&#xff0c;source 是一个内存地址&#xff08;即一个存储器操作数&#xff09;。 举个例子…...

leetcode做题笔记189. 轮转数组

给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,4…...

数据库第七章作业

本篇用于日常记录和分享 第7章作业.xls 题量: 25 满分: 100 一. 单选题&#xff08;共25题&#xff09; 1. (单选题)二级封锁协议不能保证消除&#xff08; &#xff09;这一不一致现象。 A. 读取脏数据B. 死锁C. 不可重复读D. 丢失修改 我的答案: C :不可重复读; 2. (单…...

使用服务器训练模型的注意事项

一、图像展示 1.1、用VS Code远程连接服务器时&#xff0c;当我们想用matplotlib库来进行图像展示的时候&#xff0c;需要设置DISPLAY变量。 # 用终端工具&#xff08;XShell&#xff09;SSH远程服务器&#xff0c;在终端上输入下列语句 # 如果使用了anaconda的虚拟环境&…...

Linux性能优化--性能追踪3:系统级迟缓(prelink)

12.0 概述 本章包含的例子说明了如何用Linux性能工具寻找并修复影响整个系统而不是某个应用程序的性能问题。阅读本章后&#xff0c;你将能够&#xff1a; 追踪是哪一个进程导致了系统速度的降低。用strace调查一个不受CPU限制的进程的性能表现。用strace调查一个应用程序是如…...

SpringBoot2.x简单集成Flowable

环境和版本 window10 java1.8 mysql8 flowable6 springboot 2.7.6 配置 使用IDEA创建一个SpringBoot项目 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.…...

微信小程序一键获取位置

需求 有个表单需要一键获取对应位置 并显示出来效果如下&#xff1a; 点击一键获取获取对应位置 显示在 picker 默认选中 前端 代码如下: <view class"box_7 {{ showChange1? change-style: }}"><view class"box_11"><view class"…...

Linux性能优化--使用性能工具发现问题

9.0 概述 本章主要介绍综合运用之前提出的性能工具来缩小性能问题产生原因的范围。阅读本章后&#xff0c;你将能够&#xff1a; 启动行为异常的系统&#xff0c;使用Linux性能工具追踪行为异常的内核函数或应用程序。启动行为异常的应用程序&#xff0c;使用Linux性能工具追…...

【Proteus仿真】【STM32单片机】路灯控制系统

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器&#xff0c;使用LCD1602显示模块、人体红外传感器、光线检测模块、路灯继电器控制等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示时间、工作模…...

Flutter笔记:发布一个Flutter头像模块 easy_avatar

Flutter笔记 发布一个头像Flutter模块 easy_avatar 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/1339…...

标准化助推开源发展丨九州未来参编开源领域4项团体标准正式发布

在数字中国及数字经济时代的大背景下&#xff0c;开源逐步成为各行业数字化发展的关键模式。在开源产业迅速发展的同时&#xff0c;如何评估、规范开源治理成为行业极度关注的问题。 近日&#xff0c;中电标2023年第27号团体标准公告正式发布&#xff0c;九州未来作为起草单位…...

ChatGPT对于留学生论文写作有哪些帮助?

2022年11月&#xff0c;OpenAI公司的智能聊天产品ChatGPT横空出世&#xff0c;并两个月之内吸引了超过1亿用户&#xff0c;打破了TikTok&#xff08;抖音国际版&#xff09;9个月用户破亿的纪录。 划时代的浪潮 ChatGPT的火爆立即引起了全球关注并成为热门话题&#xff0c;它…...

【yolov8目标检测】使用yolov8训练自己的数据集

目录 准备数据集 python安装yolov8 配置yaml 从0开始训练 从预训练模型开始训练 准备数据集 首先得准备好数据集&#xff0c;你的数据集至少包含images和labels&#xff0c;严格来说你的images应该包含训练集train、验证集val和测试集test&#xff0c;不过为了简单说…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道

文/法律实务观察组 在债务重组领域&#xff0c;专业机构的核心价值不仅在于减轻债务数字&#xff0c;更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明&#xff0c;合法债务优化需同步实现三重平衡&#xff1a; 法律刚性&#xff08;债…...

规则与人性的天平——由高考迟到事件引发的思考

当那位身着校服的考生在考场关闭1分钟后狂奔而至&#xff0c;他涨红的脸上写满绝望。铁门内秒针划过的弧度&#xff0c;成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定"&#xff0c;构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...