我正在编写一个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不使用扩展来确定文件类型。
有人可以告诉我这是什么问题吗?
答案 0 :(得分:1)
CompressionCodecFactory确实使用文件扩展名来确定要使用的编解码器 - 因此如果文件以.gz
结尾,则在调用getCodec
时应返回GzipCodec。如果您有.gz.2012-01-24
扩展名,那么这将不会返回gzip编解码器。因此,您需要修改文件命名约定以交换日期和扩展名。