FileInputFormat继承了抽象类InputFormat,来看一下InputFormat的源码:
public abstract class InputFormat<K, V> {
public abstract
List<InputSplit> getSplits(JobContext context) throws IOException, InterruptedException;
public abstract
RecordReader<K,V> createRecordReader(InputSplit split,TaskAttemptContext context) throws IOException, InterruptedException;
}
InputFormat 主要用于描述输入数据的格式, 它提供以下两个功能。
(1)数据切分 : 按照某个策略将输入数据切分成若干个 InputSplit, 以便确定 Map Task 个数。对应的就是getSplits方法。
(2)为 Mapper 提供输入数据: 给定某个 InputSplit, 能将其解析成一个个 key/value 对。对应的就是createRecordReader方法。
getSplits 方法主要完成数据切分的功能, 它会尝试着将输入数据切分成 InputSplit,并放入集合List中返回。
InputSplit有以下特点:
(1)逻辑分片 : 它只是在逻辑上对输入数据进行分片, 并不会在磁盘上将其切分成分片进行存储。 InputSplit 只记录了分片的元数据信息, 比如起始位置、 长度以及所在的节点列表等。
(2)可序列化: 在 Hadoop 中, 对象序列化主要有两个作用: 进程间通信和永久存储。 此处, InputSplit 支持序列化操作主要是为了进程间通信。 作业被提交到 JobTracker 之前, Client 会调用作业 InputFormat 中的 getSplits 函数, 并将得到的 InputSplit 序列
化到文件中。 这样, 当作业提交到 JobTracker 端对作业初始化时, 可直接读取该文件, 解析出所有 InputSplit, 并创建对应的 Map Task。而createRecordReader则根据InputSplit ,将其解析成一个个 key/value 对。
现在再来看FileInputFormat中对这两个方法的具体实现。
先来看FileInputFormat的定义:
public abstract class FileInputFormat<K,