RecordReader 类是实际用来加载数据并把数据转换为适合 Mapper 读取的键值对,RecordReader 由实现类自己定义。自定义 RecordReader 的主要实现方法有以下几个:
publicabstractclassRecordReader<KEYIN, VALUEIN>implementsCloseable { // 初始化,如果在构造函数中初始化了,那么该方法可以为空publicabstractvoidinitialize(InputSplitsplit, TaskAttemptContextcontext) throwsIOException, InterruptedException; //是否存在下一个key/value,如果存在返回true,否则返回falsepublicabstractbooleannextKeyValue() throwsIOException, InterruptedException; // 获取当前keypublicabstractKEYINgetCurrentKey() throwsIOException, InterruptedException; // 获取当前valuepublicabstractVALUEINgetCurrentValue() throwsIOException, InterruptedException; // 获取进度信息publicabstractfloatgetProgress() throwsIOException, InterruptedException; // 关闭资源publicabstractvoidclose() throwsIOException; }
RecordReader 会在输入块上被重复的调用直到整个输入块被处理完毕,每一次调用 RecordReader 都会调用 Mapper 的 `map()`方法。
综上所述,实现自定义输出格式的具体步骤为:
(1)定义一个类继承 InputFormat 的类,重写 `createRecordReader()` 方法,如果需要还可以重写 `isSplitable()`来设置是否切片;
(2)定义一个类继承 RecordReader 类,实现一次读取一个完整文件封装为KV类型。