1. 需求

将多个小文件合并成一个SequenceFile文件(SequenceFile文件是Hadoop用来存储二进制形式的key-value对的文件格式),SequenceFile里面存储着多个文件,存储的形式为文件路径+名称为key,文件内容为value

三个小文件

one.txt

yongpeng weidong weinan
sanfeng luozong xiaoming

two.txt

shuaige changmo zhenqiang
dongli lingu xuanxuan

three.txt

longlong fanfan
mazong kailun yuhang yixin
longlong fanfan
mazong kailun yuhang yixin

2. 需求分析

3.案例代码

1) 自定义RecordReader

package com.nty.inputformat;

import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileSplit; import java.io.IOException; /**
* author nty
* date time 2018-12-11 9:10
*/
public class CustomRecordReader extends RecordReader<Text, BytesWritable> { /**
* 由于采用了FileInputFormat的输入方式,所以输入源3个文件,会分成三个切片,所以一个RecordReader只处理一个文件,一次读完
*/ //标记文件是否被读过,true表示没被读过
private boolean flag = true; private Text key = new Text();
private BytesWritable value = new BytesWritable(); //输入流
FSDataInputStream fis; private FileSplit fs; /**
* 初始化方法,只调用一次
* @param split
* @param context
* @throws IOException
* @throws InterruptedException
*/
public void initialize(InputSplit split, TaskAttemptContext context) throws IOException, InterruptedException {
//FileSplit是InputSplit的子类
fs = (FileSplit) split; //获取文件路径
Path path = fs.getPath(); //获取文件系统
FileSystem fileSystem = FileSystem.get(context.getConfiguration());
//FileSystem fileSystem = path.getFileSystem(context.getConfiguration()); //开流
fis = fileSystem.open(path);
} /**
* 读取下一组KV
* @return 读到了返回true,反之返回false
* @throws IOException
* @throws InterruptedException
*/
public boolean nextKeyValue() throws IOException, InterruptedException {
if(flag){
//读取文件进入key和value
String path = fs.getPath().toString();
key.set(path); //文件是一次性读完,bytes的长度不能为普遍的1024,当然这么写会涉及到大文件的问题,不做讨论.
byte[] bytes = new byte[(int) fs.getLength()];
fis.read(bytes);
value.set(bytes,0,bytes.length); //重新标记
flag = false; return true;
}
return false;
} /**
* 获取当前读到的key
* @return
* @throws IOException
* @throws InterruptedException
*/
public Text getCurrentKey() throws IOException, InterruptedException {
return this.key;
} /**
* 获取当前读到的value
* @return
* @throws IOException
* @throws InterruptedException
*/
public BytesWritable getCurrentValue() throws IOException, InterruptedException {
return this.value;
} /**
* 获取当前读取的进度
* @return
* @throws IOException
* @throws InterruptedException
*/
public float getProgress() throws IOException, InterruptedException {
//文件一次读完,只有0和1的进度,根据flag来判断
return flag ? 0f : 1f;
} /**
* 关闭资源
* @throws IOException
*/
public void close() throws IOException {
IOUtils.closeStream(fis);
}
}

2) 自定义Inputformat

package com.nty.inputformat;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.JobContext;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import java.io.IOException; /**
* author nty
* date time 2018-12-11 9:09
*/
//需求中,key为文件路径+名称,所以key类型为Text,value为文件内容,用BytesWritable
public class CustomInputFormat extends FileInputFormat<Text, BytesWritable> { //最后输出的value为一个文件,所让文件不能被切分,返回false
@Override
protected boolean isSplitable(JobContext context, Path filename) {
return false;
} //返回自定义的 RecordReader
public RecordReader<Text, BytesWritable> createRecordReader(InputSplit split, TaskAttemptContext context) throws IOException, InterruptedException {
return new CustomRecordReader();
}
}

3) 编写Mapper类

package com.nty.inputformat;

import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper; import java.io.IOException; /**
* author nty
* date time 2018-12-11 9:10
*/
public class CustomMapper extends Mapper<Text, BytesWritable, Text, BytesWritable> {
@Override
protected void map(Text key, BytesWritable value, Context context) throws IOException, InterruptedException {
context.write(key,value);
}
}

4) 编写Reducer类

package com.nty.inputformat;

import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; /**
* author nty
* date time 2018-12-11 9:10
*/
public class CustomReducer extends Reducer<Text, BytesWritable, Text, BytesWritable> {
@Override
protected void reduce(Text key, Iterable<BytesWritable> values, Context context) throws IOException, InterruptedException {
for (BytesWritable value : values) {
context.write(key, value);
}
}
}

5) 编写Driver类

package com.nty.inputformat;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.BytesWritable;
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 org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat; /**
* author nty
* date time 2018-12-11 9:10
*/
public class CustomDriver { public static void main(String[] args) throws Exception{
//获取job
Configuration configuration = new Configuration();
Job job = Job.getInstance(configuration); //设置类
job.setJarByClass(CustomDriver.class);
//设置input和output
job.setInputFormatClass(CustomInputFormat.class);
job.setOutputFormatClass(SequenceFileOutputFormat.class); //设置Mapper和Reducer
job.setMapperClass(CustomMapper.class);
job.setReducerClass(CustomReducer.class); //设置Mapper和Reducer的输入输出
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(BytesWritable.class); job.setOutputKeyClass(Text.class);
job.setOutputValueClass(BytesWritable.class); //设置文件路径
FileInputFormat.setInputPaths(job, new Path("d:\\Hadoop_test"));
FileOutputFormat.setOutputPath(job, new Path("d:\\Hadoop_test_out"));
//提交
boolean b = job.waitForCompletion(true); System.exit(b ? 0 : 1); }
}

Hadoop(16)-MapReduce框架原理-自定义FileInputFormat的更多相关文章

  1. Hadoop(18)-MapReduce框架原理-WritableComparable排序和GroupingComparator分组

    1.排序概述 2.排序分类 3.WritableComparable案例 这个文件,是大数据-Hadoop生态(12)-Hadoop序列化和源码追踪的输出文件,可以看到,文件根据key,也就是手机号进 ...

  2. Hadoop(12)-MapReduce框架原理-Hadoop序列化和源码追踪

    1.什么是序列化 2.为什么要序列化 3.为什么不用Java的序列化 4.自定义bean对象实现序列化接口(Writable) 在企业开发中往往常用的基本序列化类型不能满足所有需求,比如在Hadoop ...

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

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

  4. Hadoop(15)-MapReduce框架原理-FileInputFormat的实现类

    1. TextInputFormat 2.KeyValueTextInputFormat 3. NLineInputFormat

  5. Hadoop(17)-MapReduce框架原理-MapReduce流程,Shuffle机制,Partition分区

    MapReduce工作流程 1.准备待处理文件 2.job提交前生成一个处理规划 3.将切片信息job.split,配置信息job.xml和我们自己写的jar包交给yarn 4.yarn根据切片规划计 ...

  6. Hadoop(13)-MapReduce框架原理--Job提交源码和切片源码解析

    1.MapReduce的数据流 1) Input -> Mapper阶段 这一阶段的主要分工就是将文件切片和把文件转成K,V对 输入源是一个文件,经过InputFormat之后,到了Mapper ...

  7. Hadoop(19)-MapReduce框架原理-Combiner合并

    1. Combiner概述 2. 自定义Combiner实现步骤 1). 定义一个Combiner继承Reducer,重写reduce方法 public class WordcountCombiner ...

  8. Hadoop(14)-MapReduce框架原理-切片机制

    1.FileInputFormat切片机制 切片机制 比如一个文件夹下有5个小文件,切片时会切5个片,而不是一个片 案例分析 2.FileInputFormat切片大小的参数配置 源码中计算切片大小的 ...

  9. 【Hadoop】MapReduce自定义分区Partition输出各运营商的手机号码

    MapReduce和自定义Partition MobileDriver主类 package Partition; import org.apache.hadoop.io.NullWritable; i ...

随机推荐

  1. 浅谈 java 反射机制

    一:Java反射概念 Java反射是Java被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其mod ...

  2. 结对编程的感想&收获

    关于结对编程的感想.感受,见我的另一篇随笔——<构建之法>结对编程   感想 下面我来谈谈本次结对编程的收获以及发现的问题 收获 ①这是我人生中第一次做UI界面设计,刚拿到这个题目还是比较 ...

  3. maven Could not find artifact com.** 无法下载原因分析

    1.有时候经常莫名其妙的遇到这个问题:比如在idea重新导入一个新项目,或者在原来的空间里面引入一个新项目.去私服里面查看明明是有的,但是就是下载不下来. 结合网上搜的和自己遇到的,总结原因如下: 1 ...

  4. InputStream转换为String, byte[] data = new byte[1024]详解

    /** * This file created at 2018年2月28日. * * Copyright (c) 2002-2018 Bingosoft, Inc. All rights reserv ...

  5. ps命令之排序

    Linux中ps命令会自动选择一列进行排序,但有时这不是我们想要的. 方法一: ps+sort sort 选项与参数: -f  :忽略大小写的差异,例如 A 与 a 视为编码相同:-b  :忽略最前面 ...

  6. SecureCRT ssh连接linux操作系统(解决Ubutu密钥交换失败的问题)

    我们可以使用终端软件SecureCRT 去连接linux操作系统(该SecureCRT服务走端口22,协议是ssh(类似apache走http协议,端口80)),SSH 为 Secure Shell ...

  7. UNIX高级环境编程(9)进程控制(Process Control)- fork,vfork,僵尸进程,wait和waitpid

    本章包含内容有: 创建新进程 程序执行(program execution) 进程终止(process termination) 进程的各种ID   1 进程标识符(Process Identifie ...

  8. 鸟哥私房菜vim常用命令

    第一部份:一般模式可用的按钮说明,光标移动.复制贴上.搜寻取代等 移动光标的方法 h 或 向左箭头键(←) 光标向左移动一个字符 j 或 向下箭头键(↓) 光标向下移动一个字符 k 或 向上箭头键(↑ ...

  9. 安全预警-防范新型勒索软件“BlackRouter”

    近期,出现一种新型勒索软件“BlackRouter”,开发者将其与正常软件恶意捆绑在一起,借助正常软件的下载和安装实现病毒传播,并以此躲避安全软件的查杀.目前,已知的被利用软件有AnyDesk工具(一 ...

  10. APP案例分析——嘀嗒番茄钟

    第一部分 调研, 评测 个人第一次上手体验 一直在用时间管理的软件,但是下载了卸载,来来去去也用了很多个.这个嘀嗒番茄钟也是最近比较喜欢的软件,界面简洁,功能简单,没有那么复杂非常容易上手. 功能性的 ...