Hadoop FileSplit阅读

时间:2013-04-23 22:17:36

标签: java hadoop inputstream filesplitting input-split

假设客户端应用程序使用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);
    }

在某些情况下,例如Hadoop MapReduce LineRecordReader类,会将流调整为-1。但是,FSDataInputStream seek()方法的文档明确说明,在寻找某个位置后,下一次读取将来自该位置,这意味着(?)上面的代码将关闭1个字节( ?)。

所以,问题是,那" -1"所有InputSplit阅读案例都需要调整吗?

顺便说一句,如果一个人想要正确读取FileSplit,那么寻找它的开始是不够的,因为每个分割也有一个可能与实际HDFS文件末尾不同的结尾。因此,相应的InputStream应该是"有界",即具有最大长度,如下所示:

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

在这种情况下," native"上面创建了fsin个Steam,使用了org.apache.commons.io.input.BoundedInputStream类来实现" bounding"。

更新

显然,只有对LineRecordReader类的一个用例行进行调整时才需要进行调整,这超出了分割的范围,以确保它读取完整的最后一行。

有关详细信息的详细讨论可以在earlier questionMAPREDUCE-772的评论中找到。

1 个答案:

答案 0 :(得分: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语句最有可能用于避免在换行符上开始拆分并返回空行作为第一条记录。您可以看到,如果发生搜索,则跳过第一行以确保文件拆分不返回重叠记录