Mapreduce自定义格式。在现实世界中有很多情况可以编写自定义输入和输出格式吗?

时间:2016-06-15 18:31:21

标签: hadoop mapreduce

我知道Hadoop支持各种输入和输出格式,如Text,Json,Avo,Sequence文件等。

在Hadoop的现实世界中,我们是否遇到过开发人员必须开发自定义输入和输出格式的情况。 对Hadoop世界感到遗憾。

非常感谢 纳特

1 个答案:

答案 0 :(得分:2)

  

当您需要自定义输入时,可以编写CustomInputFormat   记录阅读..

     

请参阅以下许多此类内容的CustomInputFormat示例...

示例:将段落作为输入记录阅读

如果您正在使用Hadoop MapReduce或使用AWS EMR,那么可能会有一个用例,其中输入文件将段落作为键值记录而不是单行记录(考虑分析新闻文章评论等场景)。因此,如果您需要一次处理一个完整的段落作为单个记录,那么您需要自定义**TextInputFormat**的默认行为,即默认情况下读取每一行以读取一个完整的段落,而不是将一行作为输入处理作为一个输入键值对,用于MapReduce作业中的进一步处理。

这要求我们创建一个自定义记录阅读器,可以通过实现class RecordReader来完成。您可以使用next()方法告诉记录阅读器获取段落而不是一行。请参阅以下实现,它不言自明:

public class ParagraphRecordReader implements RecordReader<LongWritable, Text> {
private LineRecordReader lineRecord;
private LongWritable lineKey;
private Text lineValue;
public ParagraphRecordReader(JobConf conf, FileSplit split) throws IOException {
lineRecord = new LineRecordReader(conf, split);
lineKey = lineRecord.createKey();
lineValue = lineRecord.createValue();
}
@Override
public void close() throws IOException {
lineRecord.close();
}
@Override
public LongWritable createKey() {
return new LongWritable();

}
@Override
public Text createValue() {
return new Text("");    
}
@Override
public float getProgress() throws IOException {
return lineRecord.getPos();    
}

@Override
public synchronized boolean next(LongWritable key, Text value) throws IOException {
boolean appended, isNextLineAvailable;
boolean retval;
byte space[] = {' '};
value.clear();
isNextLineAvailable = false;
do {
appended = false;
retval = lineRecord.next(lineKey, lineValue);
if (retval) {
if (lineValue.toString().length() > 0) {
byte[] rawline = lineValue.getBytes();
int rawlinelen = lineValue.getLength();
value.append(rawline, 0, rawlinelen);
value.append(space, 0, 1);
appended = true;
}
isNextLineAvailable = true;
}
} while (appended);

return isNextLineAvailable;
}

@Override
public long getPos() throws IOException {
return lineRecord.getPos();
}
}

使用ParagraphRecordReader实现,我们需要扩展TextInputFormat来创建一个自定义的InputFomat,只需重写getRecordReader方法并返回ParagraphRecordReader的对象来覆盖默认行为。

ParagrapghInputFormat将如下所示:

public class ParagrapghInputFormat extends TextInputFormat
{
@Override
public RecordReader<LongWritable, Text> getRecordReader(InputSplit split, JobConf conf, Reporter reporter)throws IOException {
reporter.setStatus(split.toString());
return new ParagraphRecordReader(conf, (FileSplit)split);
}
}

确保作业配置使用我们的自定义输入格式实现将数据读入MapReduce作业。它就像设置inputformat类型到ParagraphInputFormat一样简单,如下所示:

<强> conf.setInputFormat(ParagraphInputFormat.class);

通过以上更改,我们可以将段落作为输入记录读入MapReduce程序。

让我们假设输入文件如下所示:

一个简单的映射器代码如下所示:

@Override
public void map(LongWritable key, Text value, OutputCollector<Text, Text> output, Reporter reporter)
throws IOException {
System.out.println(key+" : "+value);
}