MR中的输入/输出控制

MR中的输入控制(InputFormat和MultipleInputs)

InputFormat

  1. InputFormat(输入格式化器):MapReduce开始阶段,InputFormat用来产生InputSplit,并基于RecordReader把它切分成record,形成Mapper的输入
  2. MR内置的InputFormat:
    1)TextInputFormat:作为默认的文件输入格式,用于读取纯文本文件,文件被分为一系列LF或CR结束的行,key是每一行的位置偏移量,是LongWritable类型,value是这一行的内容,Text类型。
    2)KeyValueTextInputFormat:同样用于读取文本文件,如果行被分隔符(缺省是tab)分为两部分,则第一部分是key,剩下的部分是value;如果没有分隔符,则整行都是key,value为空。
    3)SequenceFileInputFormat:用于读取sequence file。sequence file是Hadoop用于存储数据自定义格式的binary文
    件。它有两个子类:SequenceFileAsBinaryInputFormat,将 key和value以BytesWritable的类型读出;
    SequenceFileAsTextInputFormat,将key和value以Text类型读出。
    4)SequenceFileInputFilter:根据filter从sequence文件中取得部分满足条件的数据,通过 setFilterClass指定Filter,内
    置了三种 Filter,RegexFilter取key值满足指定的正则表达式的记录;PercentFilter通过指定参数f,取记录行数%f0的
    记录;MD5Filter通过指定参数f,取MD5(key)%f
    0的记录。
    5)NLineInputFormat:0.18.x新加入,可以将文件以行为单位进行split,比如文件的每一行对应一个mapper。得到的
    key是每一行的位置偏移量(LongWritable类型),value是每一行的内容,Text类型。
    6)CompositeInputFormat:用于多个数据源的join。
  3. 为MR设置指定的InputFormat:job.setInputFormatClass(xxxInputFormat.class);
  4. 自定义的InputFormat
    • 内置的输入格式化器可以应对大部分需求,但在有些需求下,内置的输入格式化器无法满足,我们需要自己定义输入格式化器。
    • 所有的InputFormat都要直接或间接继承!InputFormat抽象类!(注:也有InputFormat接口,getSplit方法的返回不一样)
    • InputFormat抽象类中主要定义了如下两个方法:
	/**
	此方法返回一个RecordReader对象
	一个RecordReader包含方法描述,如何从InputSplit中切分出要送入Mapper的key-value对
	*/
	@Override
	public RecordReader<K, V> createRecordReader(InputSplit arg0, TaskAttemptContext arg1)
			throws IOException, InterruptedException {
		return null;
	}
	/**
	生产InputSplit集合的方法
	此方法接受JobContext接受环境信息,得到要处理的文件信息后,进行逻辑切割,产生InputSplit集合返回
	*/
	@Override
	public List<InputSplit> getSplits(JobContext arg0) throws IOException, InterruptedException {
		return null;
	}
  • 在更多的时候我们不会直接继承InputFormat,而是会选择继承它的一个实现子类,
  • 比如:FlieInputFormat–此类是所有来源为文件的InputFormat的基类,默认的TextInputFormat就是继承了它
  • FileInputFormat继承了InputFormat抽象类,1)实现了getSplits方法,根据配置的逻辑切割文件,返回InputSplit的集合,2)并提供了isSplitable()方法,子类可以用过在这个方法中返回boolean类型的值表明是否要对文件进行逻辑切割,如果返回false,则无论文件的大小是否超过一个Block都不会进行切割,而将这个文件作为一个逻辑块返回,3)而对createRecordReader方法则没有提供实现,设置为抽象方法,要求子类实现
  • 如果要更精细的改变逻辑切块规则则可以覆盖getSplit方法,自己编写代码,而更多的时候直接使用父类的方法,将精力放置在决定如何将InputSplit转化为一个个的recorder
  • 注意:FileInputFormat的导包:import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

案例

读取score1.txt文件,从中每四行读取成绩,其中第一行为姓名,后三行为单科成绩,计算总分,输出 姓名:总分格式的文件

张三 
语文 97
数学 77
英语 69
李四 
语文 87
数学 57
英语 63
王五 
语文 47
数学 54
英语 39
import java.io.IOException;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.JobContext;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

public class ScoreInputFormat  extends FileInputFormat<Text, Text>{
	
	//不对文件做逻辑上的切割
	@Override
	protected boolean isSplitable(JobContext context, Path filename) {
		return false;
	}

	@Override
	public RecordReader<Text, Text> createRecordReader(InputSplit inputSplit, TaskAttemptContext context)
			throws IOException, InterruptedException {
		return new ScoreRecordReader();
	};
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;

public class ScoreRecordReader extends RecordReader<Text, Text>{
	
	private BufferedReader bfreader = null;
	private Text key=null;
	private Text value=null;
	private float progress=0f;
	
	/**
	 * RecordReader关闭前调用的方法,一般用来释放资源
	 */
	@Override
	public void close() throws IOException {
		bfreader.close();	
	}

	/**
	 * 如果nextKeyValue()方法返回true,则调用此方法获取当前的键
	 */
	@Override
	public Text getCurrentKey() throws IOException, InterruptedException {
		return key;
	}
	/**
	 * 如果nextKeyValue()方法返回true,则调用此方法获取当前的值
	 */
	@Override
	public Text getCurrentValue() throws IOException, InterruptedException {
		return value;
	}

	/**
	 * 获取当前的进度
	 */
	@Override
	public float getProgress() throws IOException, I
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值