TextInputFormat答えを見つけるには、 の実装を理解する必要があります。
コードに飛び込みましょう。新しい mapreduce API について話しますが、「古い」mapred API は非常に似ています。
あなたが言ったように、ユーザーの観点からは、TextInputFormatいくつかの改行文字に従って分割をレコードに分割します。実装を確認しましょう。
クラスがほとんど空であることがわかります。重要な機能は、次のcreateRecordように定義されています。InputFormat
@Override
public RecordReader<LongWritable, Text> createRecordReader(
InputSplit split,
TaskAttemptContext context
) {
return new LineRecordReader();
}
一般的な契約では、InputFormat を使用して RecordReader を取得します。内部MapperをMapContextImpl見ると、マッパーが RecordReader のみを使用して次のキーと値を取得していることがわかります。彼は他に何も知りません。
マッパー:
public void run(Context context) throws IOException, InterruptedException {
setup(context);
while (context.nextKeyValue()) {
map(context.getCurrentKey(), context.getCurrentValue(), context);
}
cleanup(context);
}
MapContextImpl:
@Override
public boolean nextKeyValue() throws IOException, InterruptedException {
return reader.nextKeyValue();
}
あなたが提供したこのリンクを注意深く読み直してください。次のことがわかります。
NLinesInputFormat拡張TextInputFormatし、オーバーライドのみを行います createRecordReader。基本的に を使用するのではなくLineReader、独自の を提供しますRecordReader。TextInputFormat階層の上位にある別のクラスではなく、拡張する必要があります。これは、このレベルで行われ、必要になる可能性のあるすべての処理が既に行われているためです (圧縮、分割不可能な形式など)。
NLinesRecordReader本当の仕事をします。これは、提供された から正しいオフセットでシークinitializeを取得するために必要なことを行います。また、によって使用されるものと同じものを作成しますInputStreamInputSplitLineReaderTextInputFormat
- この
nextKeyValueメソッドでは、3 つの行を取得するために 3 回呼び出されることがわかりますLineReader.readLine()(さらに、大きすぎるレコード、行末、分割の終わりなどのコーナー ケースを適切に処理するロジックもあります)。
それがあなたを助けることを願っています。重要なのは、API の全体的な設計と、各部分がどのように相互作用するかを理解することです。