【问题标题】:Hadoop FileSplit readingHadoop FileSplit 读取
【发布时间】:2013-04-23 22:17:36
【问题描述】:

假设客户端应用程序使用FileSplit 对象从相应文件中读取实际字节。

为此,必须通过以下代码从FileSplit 创建一个InputStream 对象:

    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 调整流。然而,FSDataInputStreamseek() 方法的文档明确指出,在寻找到一个位置之后,下一次读取将来自该位置,这意味着(?)上面的代码将是 1 个字节(?)。

那么,问题是,“-1”调整对于所有 InputSplit 阅读案例是否都是必要的?

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

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

在这种情况下,在上面创建了“本机”fsin 蒸汽之后,使用 org.apache.commons.io.input.BoundedInputStream 类来实现“边界”。

更新

显然,只有LineRecordReader 类之一的用例行才需要进行调整,这超出了拆分的边界,以确保它读取完整的最后一行。

可以在earlier questionMAPREDUCE-772 的cmets 中找到有关此问题的详细讨论。

【问题讨论】:

    标签: java hadoop inputstream filesplitting input-split


    【解决方案1】:

    寻找位置 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 语句很可能是为了避免从换行符开始拆分并返回空行作为第一条记录。可以看到如果出现seek,第一行会被跳过以确保文件拆分不会返回重叠记录

    【讨论】:

    • 上面的代码不会寻找-1,而是寻找start-1,即第一次之后的每个拆分开始的前一个字节。 TextInputFormat 使用的 LineRecordReader 当然可以按您所说的那样工作,因为它总是在拆分后至少再读取 1 个字节并一直持续到行尾。也许 -1 是有原因的。
    • 你能否指出表现出这种 -1 寻求行为的来源/示例
    • 网上有很多例子,但它们都与 LineReader 相关联,所以我想知道一般情况下是否会发生什么特别的事情。见鬼,例如,bigdatacircus.com/2012/08/01/…
    • 对不起,我自己的例子引用了你的问题!相应地更新了答案
    猜你喜欢
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 2020-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多