编写mapreduce程序时,发现默认对文件的输入是采用每行(\n)进行分割,能不能实现采用自定义行分割符的方式比如采用“|-|\n”作为行分割符呢
来看看hadoop默认是怎样实现的:
public class TextInputFormat extends FileInputFormat<LongWritable, Text> {@Overridepublic RecordReader<LongWritable, Text> 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);}
//这个对文件做压缩用的@Overrideprotected 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"逐行读取了,而是以用户自定义的行分割符来作为“行”(可能是一行或者多行)读取文件内容了。