使用自定义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 - 您的输入流已经解压。
我不知道Hadoop为您处理了GZIP,现在几天来一直困扰着这个问题。谢谢你清理它 – Shane 2013-02-11 13:55:22