InputFormat接口(package org.apache.hadoop.mapreduce包中)里包括两个方法:getSplits()和createRecordReader(),这两个方法分别用来定义输入分片和读取分片的方法。
1 public abstract class InputFormat<K, V> {
2
3 public abstract
4 List<InputSplit> getSplits(JobContext context
5 ) throws IOException, InterruptedException;
6
7
8 public abstract
9 RecordReader<K,V> createRecordReader(InputSplit split,
10 TaskAttemptContext context
11 ) throws IOException,
12 InterruptedException;
13 }
getSplits()负责将文件切分成多个分片(InputSplit),但InputSplit并没有实际切分文件,而只是说明了如何切分数据,也就是说,InputSplit只是逻辑上的切分。createRecordReader()则创建了RecordReader,用来从InputSplit读取记录。
再看InputSplit类,它包括了getLength()和getLocation()两个方法。getLength()方法用来获取InputSplit的大小,getLocation()则用来获取InputSplit的位置。
1 public abstract class InputSplit {
2
3 public abstract long getLength() throws IOException, InterruptedException;
4
5 public abstract
6 String[] getLocations() throws IOException, InterruptedException;
7 }
每个InputSplit对应一个map任务。作为map的输入,在逻辑上提供了这个map任务所要处理的key-value对。
InputSplit只是定义了如何切分文件,但并没有定义如何访问它,这个工作由RecordReader来完成。RecordReader的实例是由InputFormat定义的。例如,在InputFormat的默认子类TextInputFormat中,提供了LineRecordReader。
1 package org.apache.hadoop.mapreduce.lib.input;
2
3 public class TextInputFormat extends FileInputFormat<LongWritable, Text> {
4
5 @Override
6 public RecordReader<LongWritable, Text>
7 createRecordReader(InputSplit split,
8 TaskAttemptContext context) {
9 return new LineRecordReader();
10 }
LineRecordReader会把文件的每一行作为一个单独的记录,并以行偏移为键值。这也就解释了WordCount例子中,行偏移为key值,每一行的内容作为value的原因。
本文基于hadoop1.2.1
如有错误,还请指正
参考文章:《Hadoop应用开发技术详解》 刘刚