2

在 Hadoop 中,我有一个 3GB 大小的序列文件。我想并行处理它。因此,我将创建 8 个 maptasks 和 8 个 FileSplits。

FileSplit 类的构造函数需要:

Path of the file
Start position
Length

例如,第一次拆分可以从 0 开始,长度为 3GB/8,下一次从 3GB/8 开始,长度为 3GB/8,依此类推。

现在 SequenceFile.Reader 有一个相同的构造函数:

Path of the file
Start position
Length

对于第一次拆分(从 0 开始,长度为 3Gb/8),序列文件能够读取它,因为它包含文件头、压缩类型以及有关键和值类的信息。

但是,对于其他拆分,SequenceFile.Reader 无法读取拆分,因为我认为文件的该部分不包含序列文件的标头(因为文件拆分不是从 0 开始),因此当我尝试使用序列文件时,它会抛出 NullPointerException。

那么有没有办法从序列文件中分割文件?

4

1 回答 1

0

好吧,这个想法是SequenceFile.Reader的开始长度参数不是用于指定序列文件的一部分,而是用于指定序列文件的真实开始跨度(例如,如果您有一个包含五个序列的容器文件文件在一起,并且您想使用其中一个,因此请指定该容器文件中序列文件的开始和长度。或者如果您想从序列文件的开头读取到特定长度;但是不能将开始设置为序列文件的中间,因为您将跳过序列文件的标题并且您将得到“不是序列文件错误”,因此您必须将开始参数设置为开头序列文件)。

因此,解决方案是像往常一样在 InputFormat 中创建文件拆分:

new FileSplit(path, start, span, hosts);

然后像往常一样在 RecordReader 中创建序列阅读器(无需指定开始或长度):

reader = new SequenceFile.Reader(fs, path, conf);// As usual
start = Split.getStart();
reader.sync(start);

这个想法在“同步”中,它跳过了拆分的“开始”指定的字节数。


对于RecordReadernextKeyValue

    if ((reader.getPosition() >= (start + span)) || !reader.next(key, value)) {
        return false;
    } else {
        return true;
    }
于 2017-04-13T12:12:27.600 回答