概述
InputFormat是MapReduce用于处理数据输入的一个最顶级的抽象父类
InputFormat实现结构
InputFormat抽象类仅有两个抽象方法:
List<InputSplit> getSplits
(), 获取由输入文件计算出输入分片(InputSplit),解决数据或文件分割成片问题。RecordReader<K,V>
createRecordReader
(),创建RecordReader
,从InputSplit
中读取数据,每一个split
读取一次。
以TextInputFormat为例:
RecordReader
从split
中读取数据,每一行生成一个k1,v1
。再经过map()
处理后生成k2,v2
。直到读取完整个split
(多少数据生成一个k,v根据RecordReader
内部实现决定,如1行文本生成一个k,v。n行文本生成一个k,v。整个文本生成一个k,v等)
//部分源码
public RecordReader<LongWritable, Text>
createRecordReader(InputSplit split, TaskAttemptContext context) {
String delimiter =
context.getConfiguration().get("textinputformat.record.delimiter");
byte[] recordDelimiterBytes = null;
if (null != delimiter) {
recordDelimiterBytes = delimiter.getBytes();
}
return new LineRecordReader(recordDelimiterBytes);
}
FileInputFormat
FileInputFormat常用类
类名 | 主要作用 | 调用Map次数 |
---|---|---|
TextInputFormat | 读取文本文, | 每一行调用一次Mapper |
CombineInputFormat | 在MR当中用于合并小文件,将多个小文件合并之后只需要启动一个mapTask进行运行 | |
SequenceInputFormat | 处理SequenceFile这种格式的数据 | |
KeyValueInputFormat | 通过手动指定分隔符,将每一条数据解析成为key,value对类型 | 每一个K,V对调用一次Mapper |
NLineInputFormat | 指定数据的行数作为一个切片 | 每N行调用一次Mapper |
FixedLengthInputFormat | 从文件中读取固定宽度的二进制记录 | 每定长数据一个 |
KeyValueTextInputFormat
KeyValueTextInputFormat
通过自定义分隔符来区分key
和value
。
如果没有分隔符,则整行是key
,value
是null
默认分割符是\t
源码
public KeyValueLineRecordReader(Configuration conf) throws IOException {
String sepStr = conf.get("key.value.separator.in.input.line", "\t");
this.separator = (byte)sepStr.charAt(0);
}
//main
public class KeyValueInputDemo extends Configured implements Tool{
public static void main (String[] args) throws Exception {
Configuration conf = new Configuration();
conf.set("key.value.separator.in.input.line","@test@");
int run = ToolRunner.run(conf, new KeyValueInputDemo(),args);
System.exit(run);
}
@Override
public int run(String[] args) throws Exception {
Configuration conf = super.getConf();
Job job = Job.getInstance(conf);
KeyValueTextInputFormat.addInputPath(job,new Path("file:///F:\\BigData\\project\\hadoop\\data\\keyValueInputData\\testData.txt"));
//第一步:读取文件,解析成为key,value对
job.setInputFormatClass(KeyValueTextInputFormat.class);
//第二步:设置mapper类
job.setMapperClass(MyMapper.class);
job.setMapOutputKeyClass(Text.class);
job.