用户定制mapreduce输入输出格式
1.hadoop内置的数据输入格式
<1>TextInputFormat
系统默认的数据输入格式,可以将文本文件分块并逐行读入以便map节点进行处理,所产生的key就是当前行的首字母在整个文本文件中的字节偏移位置,value就是该行的内容
<2>KeyValueTextInputFormat
一种常用的数据输入的格式,可将一个按照<key,value>格式逐行存放的文本文件逐行读出,并自动解析成相应的key和value
RecordReader
对于一种数据输入格式都要有一个对应的RecordReader,它主要用于将一个文件中的数据记录分拆成具体的键值对,传送给Map过程作为键值对输入参数
TextInputFormat-------LineRecordReader
KeyValueTextFormat----KeyValueLineRecordReader
<3>其他的数据输入格式
AutoInputFormat
CombineFileInputFormat
CompositeInputFormat
DBInputFormat
FileInputFormat
LineDocInputFormat
MultiFileInputFormat
NlineInputFormat
SequenceFileAsBinaryInputFormat
SequenceFileAsTextInputFormat
SequenceFileInputFormat
StreamInputFormat
2.用户定制数据输入格式与RecordReader
public class FileNameLocInputFormat extends FileInputFormat<Text, Text> {@Overridepublic RecordReader<Text, Text> createRecordReader(InputSplit split,TaskAttemptContext context) {FileNameLocInputFormat fnrr = new FileNameLocInputFormat();try {fnrr.initialize(split, context);} catch (Exception e) {e.printStackTrace();}return fnrr;}}public class FileNameLocRecordReader extends RecordReader<Text, Text> {String FileName;LineRecordReader lrr = new LineRecordReader();@Overridepublic Text getCurrentKey() throws Exception {return new Text("(" + FileName + "@" + lrr.getCurrentKey() + ")");}@Overridepublic Text getCurrentValue() throws Exception {return lrr.getCurrentValue();}@Overridepublic void initialize(InputSplit split,TaskAttemptContext arg1)throws Exception{lrr.initialize(arg0,arg1);FileName=((FileSplit)arg0).getPath().getName();}}
?上述代码是将数据输入的格式自定义为“FileName@LineOffset”的格式啦,也就是“文件名@该行在文档中的偏移量”
在使用的时候,使用job指定数据输入的格式即可
job.setInputFormatClass(FileNameLocInputFormat.class);
3.hadoop内置的数据输出格式
<1>TextOutputFormat
?系统默认的数据输出格式,可以将计算结果按照key value对的形式逐行的输出到文本文件中
TextOutputFormat-----LineRecordWriter
<2>其他数据输出格式(用到是再进行查询即可)
4.通过定制数据的输出格式实现多集合文件输出
例如:我分析日志时,我希望结果输入是按照多文件输入的并可以按照相应的时间进行命名,例如分析专利数据时,我希望结果是将每个国家的专利信息存放在不同国家的目录中去
public static class MapClass extendsMapper<LongWritable, Text, NullWritable, Text> {public void map(LongWritable key, Text value, Context context)throws exception {context.write(NullWritable.get(), value);}public static class SaveByCountryOutputFormat extendsMultipleTextOutputFormat<NullWritable, Text> {protected String generateFileNameForKeyValue(NullWritable key,Text value, String filename) {String[] dataRecord = value.toString().split(",", -1);// 获取国家的缩写名String country = dataRecord[4].substring(1.3);return country + "/" + filename;}}}
?在使用时候,只需要利用job来设置数据输出的格式即可
job.setOutputFormat(SaveByCountryOutputFormat.class);