使用自定义RecordReader与大文件时出现堆错误

问题描述:

我写了一个自定义文件读取器,因为它们是大的gzip文件,因此我不想分割我的输入文件,我希望我的第一个mapper工作只需简单地对它们进行gunzip。我遵循'Hadoop权威指南'中的示例,但在尝试读入BytesWritable时出现堆错误。我相信这是因为字节数组的大小是85713669,但我不知道如何解决这个问题。使用自定义RecordReader与大文件时出现堆错误

下面是代码:

public class WholeFileRecordReader extends RecordReader<NullWritable, BytesWritable> { 

private FileSplit fileSplit; 
private Configuration conf; 
private BytesWritable value = new BytesWritable(); 
private boolean processed = false; 

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

@Override 
public NullWritable getCurrentKey() throws IOException, 
     InterruptedException { 
    return NullWritable.get(); 
} 

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

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

@Override 
public void initialize(InputSplit split, TaskAttemptContext context) 
     throws IOException, InterruptedException { 
    this.fileSplit = (FileSplit) split; 
    this.conf = context.getConfiguration(); 
} 

@Override 
public boolean nextKeyValue() throws IOException, InterruptedException { 
    if (!processed) { 
     byte[] contents = new byte[(int) fileSplit.getLength()]; 
     Path file = fileSplit.getPath(); 
     FileSystem fs = file.getFileSystem(conf); 
     FSDataInputStream in = null; 
     try { 
      in = fs.open(file); 
      IOUtils.readFully(in, contents, 0, contents.length); 
      value.set(contents, 0, contents.length); 
     } finally { 
      IOUtils.closeStream(in); 
     } 
     processed = true; 
     return true; 
    } 
    return false; 
} 

}

一般来说,你不能整个文件加载到Java虚拟机的内存。 您应该找到一些流解决方案来处理大文件 - 按块读取数据块并保存结果而不修复内存整个数据集
此特定任务 - 解压缩可能不适用于MR,因为没有逻辑分区的数据存入记录。
请注意,hadoop会自动处理gzip - 您的输入流已经解压。

+0

我不知道Hadoop为您处理了GZIP,现在几天来一直困扰着这个问题。谢谢你清理它 – Shane 2013-02-11 13:55:22