当前位置: 首页 > 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;不过为了简单说…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...