何时为Map减少作业的自定义输入格式

时间:2016-05-24 06:17:20

标签: hadoop mapreduce

在使用Map Reduce编程时,我们何时应该使用自定义输入格式?

假设我有一个文件,我需要逐行读取它有15个由管道分隔的列,我应该去自定义输入格式吗?

在这种情况下,我可以使用TextInput格式以及自定义输入格式。

2 个答案:

答案 0 :(得分:3)

  

当您需要自定义输入时,可以编写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);
}

答案 1 :(得分:0)

是的,你可以使用TextInputformat作为案例。