1

FileSplit対応するファイルから実際のバイトを読み取るためにオブジェクトを使用するクライアント アプリケーションを想定します。

そのためには、次のようなコードを使用InputStreamして からオブジェクトを作成する必要があります。FileSplit

    FileSplit split = ... // The FileSplit reference
    FileSystem fs   = ... // The HDFS reference

    FSDataInputStream fsin = fs.open(split.getPath());

    long start = split.getStart()-1; // Byte before the first

    if (start >= 0)
    {
        fsin.seek(start);
    }

-1 によるストリームの調整は、Hadoop MapReduce LineRecordReaderクラスなどのいくつかのシナリオに存在します。ただし、FSDataInputStream seek()メソッドのドキュメントには、特定の場所をシークした後、次の読み取りはその場所から行われることが明示的に示されています。これは、上記のコードが 1 バイトずれている (?) ことを意味します (?)。

問題は、すべての InputSplit 読み取りケースで「-1」の調整が必要かどうかです。

ところで、FileSplit正しく読みたい場合は、その開始点までシークするだけでは十分ではありません。これは、すべての分割にも、実際の HDFS ファイルの終了点とは異なる終了点がある可能性があるためです。したがって、対応するInputStreamものは「制限」されている必要があります。つまり、次のように最大長があります。

    InputStream is = new BoundedInputStream(fsin, split.getLength());

この場合、fsin上で「ネイティブ」ストリームを作成した後、org.apache.commons.io.input.BoundedInputStreamクラスを使用して「境界」を実装します。

アップデート

どうやら調整は、LineRecordReader最後の行全体を確実に読み取るために分割の境界を超えるクラスの 1 つのユース ケースにのみ必要です。

これに関するより詳細な議論は、以前の質問MAPREDUCE-772のコメントにあります。

4

1 に答える 1

2

位置 0 へのシークは、InputStream.read() への次の呼び出しがバイト 0 を読み取ることを意味します。位置 -1 へのシークは、おそらく例外をスローします。

例やソースコードで標準パターンについて話すとき、具体的にどこを指していますか?

ご指摘のとおり、分割は必ずしも制限されているわけではありません。例として TextInputFormat と分割可能なファイルを取り上げます。分割を処理するレコード リーダーは、次のことを行います。

  • 開始インデックスにシークし、次の改行文字を見つける
  • 次の改行文字 (または EOF) を見つけて、その「行」を次のレコードとして返します

これは、見つかった次の改行が分割の終わりを超えるか、EOF が見つかるまで繰り返されます。したがって、この場合、分割の実際の境界は、入力分割によって指定されたものから右にシフトされる可能性があることがわかります

アップデート

LineRecordReader からこのコード ブロックを参照します。

if (codec != null) {
  in = new LineReader(codec.createInputStream(fileIn), job);
  end = Long.MAX_VALUE;
} else {
  if (start != 0) {
    skipFirstLine = true;
    --start;
    fileIn.seek(start);
  }
  in = new LineReader(fileIn, job);
}
if (skipFirstLine) {  // skip first line and re-establish "start".
  start += in.readLine(new Text(), 0,
                       (int)Math.min((long)Integer.MAX_VALUE, end - start));
}

この--startステートメントはおそらく、改行文字で始まる分割を回避し、最初のレコードとして空の行を返すことに対処するためのものです。シークが発生した場合、ファイル分割で重複するレコードが返されないように、最初の行がスキップされることがわかります。

于 2013-04-23T23:31:53.397 に答える