MR案例:定制InputFormat
数据输入格式
InputFormat类用于描述MR作业的输入规范,主要功能:输入规范检查(比如输入文件目录的检查)、对数据文件进行输入切分和从输入分块中将数据记录逐一读取出来、并转化为Map的输入键值对。细节详见解读:标准输入/输出格式
Hadoop中最常用的数据输入格式包括:TextInputFormat 和 KeyValueInputFormat。
1). TextInputFormat 是系统默认的数据输入格式,可以将文件的每一行解析成一个键值对。其中,Key是当前行在整个文件中的字节偏移量,而Value就是该行的内容。默认的RecordReader是LineRecordReader。
2). KeyValueInputFormat是将一个按照<key,value>格式存放的文本文件逐行读出,并自动解析生成相应的key和value。默认是KeyValueLineRecordReader。
定制数据输入格式
用户可以从基类 InputFormat 和 RecordReader 开始定制过程,主要实现 InputFormat 中的 createRecordReader() 和 getSplits() 两个抽象方法,而 RecordReader 中则需要实现 gerCurrentKey() 和 getCurrentValue() 几个抽象方法。
需求:为了能更细粒的记录每个单词在文档中出现时的行位置信息FileName@LineOffset。
- 方法一:基于默认的TextInputFormat和LineRecordReader
public static class IIMapper extends Mapper<Text, Text, Text, Text>{
@Override
//输出key:word 输出value:FileName@LineOffset
protected void map(Text key, Text value,Context context)
throws IOException, InterruptedException {
//得到输入文件的文件名FileName(优化:应在setup方法中获取)
FileSplit fileSplit = (FileSplit)context.getInputSplit();
String name = fileSplit.getPath().getName();
//组装拼接Value: FileName@LineOffset
Text fileName_lineOffset=new Text(name+"@"+key.toString());
String[] splited = value.toString().split("\t");
for(String word : splited){
context.write(new Text(word), fileName_lineOffset);
}
}
}
- 方法二:基于 TextInputFormat 和 LineRecordReader 定制 FileNameInputFormat 和 FileNameRecordReader
package invertedIndex; import java.io.IOException; 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 org.apache.hadoop.mapreduce.lib.input.LineRecordReader; public class FileNameRecordReader extends RecordReader<Text, Text> { //成员变量
String fileName;
//实例化一个LineRecordReader实例
LineRecordReader lrr=new LineRecordReader(); @Override
public void initialize(InputSplit split, TaskAttemptContext context)
throws IOException, InterruptedException { //调用LineRecordReader类的初始化方法
lrr.initialize(split, context); //获取当前InputSplit的文件名
fileName=((FileSplit)split).getPath().getName();
} @Override
public Text getCurrentKey() throws IOException, InterruptedException { //调用LineRecordReader类的方法,拼接key
//其中lrr.getCurrentKey()返回:当前行在整个文本文件中的字节偏移量
return new Text("("+fileName+"@"+lrr.getCurrentKey().toString()+")");
} @Override
public Text getCurrentValue() throws IOException, InterruptedException { //调用LineRecordReader类的方法
return lrr.getCurrentValue();
} @Override
public boolean nextKeyValue() throws IOException, InterruptedException { return lrr.nextKeyValue();
} @Override
public float getProgress() throws IOException, InterruptedException { return lrr.getProgress();
} @Override
public void close() throws IOException { lrr.close();
}
} package invertedIndex; import java.io.IOException; 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.FileInputFormat; public class FileNameInputFormat extends FileInputFormat<Text, Text>{ @Override
public RecordReader<Text, Text> createRecordReader(InputSplit split,
TaskAttemptContext context) throws IOException, InterruptedException { FileNameRecordReader fnrr = new FileNameRecordReader(); //调用FileNameRecordReader的初始化方法
fnrr.initialize(split, context); return fnrr;
}
}
- 使用自定义的 FileNameInputFormat 和 FileNameRcordReader :
package invertedIndex; import java.io.IOException;
import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
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; public class InvertedIndex {
public static void main(String[] args) throws Exception {
Job job = Job.getInstance(new Configuration());
job.setJarByClass(InvertedIndex.class);
//设置数据输入格式【使用自定义的InputFormat】
job.setInputFormatClass(FileNameInputFormat.class);
job.setMapperClass(FFMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
job.setNumReduceTasks(0);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
job.waitForCompletion(true);
} public static class FFMapper extends Mapper<Text, Text, Text, Text>{
@Override
protected void map(Text key, Text value, Context context)
throws IOException, InterruptedException {
//分词
StringTokenizer st = new StringTokenizer(value.toString());
for(;st.hasMoreTokens();){
//key:单词word value:FileName+偏移量
context.write(new Text(st.nextToken()), key);
}
}
}
}
输出结果为:key:单词,value:FileName@偏移量
read (data1@0)
file (data1@0)
read (data1@11)
data (data1@11)
数据输出格式
数据输出格式(OutputFormat)用于描述MR作业的数据输出规范。主要功能:输出规范检查(如检查输出目录是否存在),以及提供作业结果数据输出功能。
Hadoop默认的数据输出格式是TextOutputFormat,可以将结果以【key+\t+value】的形式逐行输出。默认的RecordWriter是LineRecordWriter。
MR案例:定制InputFormat的更多相关文章
- MR案例:倒排索引
1.map阶段:将单词和URI组成Key值(如“MapReduce :1.txt”),将词频作为value. 利用MR框架自带的Map端排序,将同一文档的相同单词的词频组成列表,传递给Combine过 ...
- MR案例:Reduce-Join
问题描述:两种类型输入文件:address(地址)和company(公司)进行一对多的关联查询,得到地址名(例如:Beijing)与公司名(例如:Beijing JD.Beijing Red Star ...
- MR案例:小文件处理方案
HDFS被设计来存储大文件,而有时候会有大量的小文件生成,造成NameNode资源的浪费,同时也影响MapReduce的处理效率.有哪些方案可以合并这些小文件,或者提高处理小文件的效率呢? 1). 所 ...
- MR案例:定制Partitioner
可以继承基类Partitioner,也可以继承默认的HashPartitioner类,覆写其中的 getPartition() 方法实现自己的分区. 需求:本例是对上一个实例的改写,需求不变 pack ...
- MR案例:CombineFileInputFormat
CombineFileInputFormat是一个抽象类.Hadoop提供了两个实现类CombineTextInputFormat和CombineSequenceFileInputFormat. 此案 ...
- MR案例:倒排索引 && MultipleInputs
本案例采用 MultipleInputs类 实现多路径输入的倒排索引.解读:MR多路径输入 package test0820; import java.io.IOException; import j ...
- MR案例:输出/输入SequenceFile
SequenceFile文件是Hadoop用来存储二进制形式的key-value对而设计的一种平面文件(Flat File).在SequenceFile文件中,每一个key-value对被看做是一条记 ...
- MR案例:小文件合并SequeceFile
SequeceFile是Hadoop API提供的一种二进制文件支持.这种二进制文件直接将<key, value>对序列化到文件中.可以使用这种文件对小文件合并,即将文件名作为key,文件 ...
- MR案例:MR和Hive中使用Lzo压缩
在MapReduce中使用lzo压缩 1).首先将数据文件在本地使用lzop命令压缩.具体配置过详见配置hadoop集群的lzo压缩 //压缩lzop,解压缩lzop -d [root@ncst wo ...
随机推荐
- 160419、CSS3实现32种基本图形
CSS3可以实现很多漂亮的图形,我收集了32种图形,在下面列出.直接用CSS3画出这些图形,要比贴图性能更好,体验更加,是一种非常好的网页美观方式. 这32种图形分别为圆形,椭圆形,三角形,倒三角形, ...
- 20165330 2017-2018-2 《Java程序设计》第2周学习总结
课本知识总结 第二章 基本数据类型与数组 标识符:标识类名.变量名.方法名.类型名.数组名及文件名的有效字符序列. 标识符的第一个字符不能是数字字符,且字母区分大小写. Java语言使用Unicode ...
- ORACLE安装(12c-Redhat6.5)
Oracle安装(12c-Redhat6.5) Redhat6.5系统准备 / 10G SWAP 4G /boot 200M /HOME 4G /usr 8G /var 4G /u01 Preinst ...
- 干货 | 蚂蚁金服是如何实现经典服务化架构往 Service Mesh 方向的演进的?
干货 | 蚂蚁金服是如何实现经典服务化架构往 Service Mesh 方向的演进的? https://www.sohu.com/a/235575064_99940985 干货 | 蚂蚁金服是如何实现 ...
- Spark Standalone Mode 单机启动Spark -- 分布式计算系统spark学习(一)
spark是个啥? Spark是一个通用的并行计算框架,由UCBerkeley的AMP实验室开发. Spark和Hadoop有什么不同呢? Spark是基于map reduce算法实现的分布式计算,拥 ...
- 前端框架之SweetAlert
简介 SweetAlert是一款很好用的弹出框框架 下载 点我下载 导入 博主用的是bootstrap-sweetalert,所以要依赖bootstrap,导入前先导入原生jQuery以及bootst ...
- 基于stm32CubeMX和keil5的stm32f103学习编程
0. 准备 先用st-link连接stm32核心板与PC,用于烧录 St-link Stm32 3.3V 3.3V GND GND SWDIO DIO SWCLK DCLK 再用USB串口 ...
- POJ 3171
题目大意: 给定一个区间范围[M,E],接下来有n行输入.每行输入三个数值:T1,T2,S,表示覆盖区间[T1,T2] 的代价为S,要求你求出覆盖区间[M,E]的最小代价,假设不能覆盖, ...
- POJ3176:Cow Bowling(数字三角形问题)
地址:http://poj.org/problem?id=3176 题目解析:没什么好说的,之前上课时老师讲过.从下往上找,每一个三角形的顶点可由两个角加上顶点的值 两种方式得到 ,用dp数组保存下最 ...
- ORACLE USERENV函数
ORACLE USERENV函数 USERENV返回关于当前会话的信息.此信息可以用于编写一个应用程序特定的审计跟踪表或确定特定于语言的角色目前使用的会话. 参数 功能 CLINET_INFO 返回最 ...