编写mapreduce程序时,发现默认对文件的输入是采用每行(\n)进行分割,能不能实现采用自定义行分割符的方式比如采用“|-|\n”作为行分割符呢
来看看hadoop默认是怎样实现的:
public class TextInputFormat extends FileInputFormat {
@Override
public RecordReader
createRecordReader(InputSplit split,
TaskAttemptContext context) {
String delimiter = context.getConfiguration().get(
"textinputformat.record.delimiter");
byte[] recordDelimiterBytes = null;
if (null != delimiter)
recordDelimiterBytes = delimiter.getBytes(Charsets.UTF_8);
return new LineRecordReader(recordDelimiterBytes);
}
//这个对文件做压缩用的
@Override
protected boolean isSplitable(JobContext context, Path file) {
final CompressionCodec codec =
new CompressionCodecFactory(context.getConfiguration()).getCodec(file);
if (null == codec) {
return true;
}
return codec instanceof SplittableCompressionCodec;
}
}
TextInputFormat类是继承自FileInputFormat ,FileInputFormat 实现了 InputFormat接口
TextInputFormat中可以看到,在getRecordReader函数中调用了LineRecordReader这个类。我们注意观察在传入的参数中有一个delimiter参数,这个参数就是用来指定分割符的(具体可以查看LineRecordReader中实现对文件分割的实现),所以我们可以自己定义一个类MyInputFormat继承FileInputFormat类然后将
String delimiter = context.getConfiguration().get(
"textinputformat.record.delimiter");
改为:String delimiter = "|-|\n";
然后在程序中,在Job中设置InputFormat类为MyInputFormat.class即可。
job.setInputFormatClass(MyInputFormat.class);
如果不选择重写InputFormat类,也是可以实现的,给参数Configuaration对象设置属性textinputformat.record.delimiter
以下是伪代码示例
private int run(long cols, String data_length, String primarykey_order_id, Configuration conf)
throws IOException, ClassNotFoundException, InterruptedException, SQLException
{
conf.set("colnumSize", String.valueOf(cols));
conf.set("textinputformat.record.delimiter", "|-|\n");
Job job = new Job(conf, JobUtil.getJobName(dataTime, interfaceCode));
job.setJarByClass(RunTxt.class);
job.setMapperClass(Mapper_RunTxt.class);
// job.setInputFormatClass(MyTextFormat.class);
}
这样程序读取文本时不再以原来默认的"\n"逐行读取了,而是以用户自定义的行分割符来作为“行”(可能是一行或者多行)读取文件内容了。