使用自定义RecordReader在Hadoop中读取gzip压缩文件

时间:2013-01-24 09:12:01

标签: hadoop mapreduce

我正在编写一个MapReduce代码,我必须将文件名作为键读取,文件内容作为其值。为此,我发布了this question on StackOverflow。它为文本文件工作文件,但开始给gzip文件带来问题。所以参考LineRecordReader类我在代码中做了一些修改。代码段是:

public class WholeFileRecordReader extends RecordReader<Text, BytesWritable> {

    private CompressionCodecFactory compressionCodecs = null;
    private FileSplit fileSplit;
    private Configuration conf;
    private InputStream in;
    private Text key = new Text("");
    private BytesWritable value = new BytesWritable();
    private boolean processed = false;

    @Override
    public void initialize(InputSplit split, TaskAttemptContext context)
            throws IOException, InterruptedException {

        this.fileSplit = (FileSplit) split;
        this.conf = context.getConfiguration();

        final Path file = fileSplit.getPath();
        compressionCodecs = new CompressionCodecFactory(conf);

        final CompressionCodec codec = compressionCodecs.getCodec(file);
        System.out.println(codec);
        FileSystem fs = file.getFileSystem(conf);
        in = fs.open(file);

        if (codec != null) {
            in = codec.createInputStream(in);
        }
    }

    @Override
    public boolean nextKeyValue() throws IOException, InterruptedException {
        if (!processed) {
            byte[] contents = new byte[(int) fileSplit.getLength()];
            Path file = fileSplit.getPath();
            key.set(file.getName());

            try {
                IOUtils.readFully(in, contents, 0, contents.length);
                value.set(contents, 0, contents.length);
            } finally {
                IOUtils.closeStream(in);
            }

            processed = true;
            return true;
        }

        return false;
    }

    @Override
    public Text getCurrentKey() throws IOException, InterruptedException {
        return key;
    }

    @Override
    public BytesWritable getCurrentValue() throws IOException, InterruptedException {
        return value;
    }

    @Override
    public float getProgress() throws IOException {
        return processed ? 1.0f : 0.0f;
    }

    @Override
    public void close() throws IOException {
        // Do nothing
    }

}

问题在于我将codec对象的值设为null,尽管该文件是 gz 文件。有一点需要注意的是,为了我自己的目的,我最后在日期中添加了日期。但我觉得这应该不是问题,因为我听说Unix不使用扩展来确定文件类型。

有人可以告诉我这是什么问题吗?

1 个答案:

答案 0 :(得分:1)

CompressionCodecFactory确实使用文件扩展名来确定要使用的编解码器 - 因此如果文件以.gz结尾,则在调用getCodec时应返回GzipCodec。如果您有.gz.2012-01-24扩展名,那么这将不会返回gzip编解码器。因此,您需要修改文件命名约定以交换日期和扩展名。