hadoop的inputformat问题

一、概述

  1. MapReduce开始阶段阶段,InputFormat类用来产生InputSplit,并把基于RecordReader它切分成record(即KEYIN-VALUEIN),形成Mapper的输入。
  2. Hadoop本身提供了若干内置的InputFormat,其中如果不明确指定默认使用TextInputFormat。

 

二、常见子类

  1. TextInputFormat:作为默认的文件输入格式,用于读取纯文本文件,文件被分为一系列以LF(Line-Feed 换行)或者CR(Carriage-Return 回车)结束的行,key是每一行的数据位置偏移量,是LongWritable类型的,value是每一行的内容,为Text类型。
  2. KeyValueTextInputFormat:同样用于读取文本文件,如果行被分隔符(默认是\t)分割为两部分,第一部分为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,取记录行数%f==0的记录;MD5Filter通过指定参数f,取MD5(key)%f==0的记录。
  5. NLineInputFormat:0.18.x新加入,可以将文件以行为单位进行split,将文件的每一行对应一个mapper。得到的key是每一行的位置偏移量(LongWritable类型),value是每一行的内容,Text类型。适合于行数不多但是每一行的字段较多的场景
  6. CompositeInputFormat:用于多个数据源的join
  7. DBInputFormat:把数据库表数据读入到HDFS

 

三、自定义输入格式

概述

  1. 所有InputFormat都要直接或间接的继承InputFormat抽象类
  2. InputFormat中主要定义了如下两个方法:getSplits以及createRecordReader
  3. 如果数据来源是文件,那么可以继承FileInputFormat。FileInputFormat实现了InputFormat接口,实现了getSplits方法,根据配置去逻辑切割文件,返回FileSplit的集合,并提供了isSplitable()方法,子类可以通过在这个方法中返回boolean类型的值表明是否要对文件进行逻辑切割,如果返回false则无论文件是否超过一个Block大小都不会进行切割,而将这个文件作为一个逻辑块返回。而对createRecordReader方法则没有提供实现,设置为了抽象方法,要求子类实现。
  4. TextInputFormat继承了FileInputFormat

案例

// 格式类

public class AutoInputFormat extends FileInputFormat<Text, Text>{

    

    @Override

    protected boolean isSplitable(JobContext context, Path filename) {

        return false;

    }



    @Override

    public RecordReader<Text, Text> createRecordReader(InputSplit split, TaskAttemptContext context)

            throws IOException, InterruptedException {

        return new AutoRecordReader();

    }



}

// 读取类

public class AutoRecordReader extends RecordReader<Text, Text> {

    private LineReader reader;

    private Text key;

    private Text value;



    @Override

    public void initialize(InputSplit split, TaskAttemptContext context) throws IOException, InterruptedException {



        // 获取文件分片

        FileSplit fs = (FileSplit) split;

        // 通过分片获取文件路径

        Path path = fs.getPath();

        // 获取环境配置

        Configuration conf = context.getConfiguration();

        // 获取文件系统

        FileSystem system = FileSystem.get(URI.create(path.toString()), conf);

        // 获取输入流

        FSDataInputStream in = system.open(path);

        // 将该字节流包装成一个LineReader对象方便按行读取

        reader = new LineReader(in);



    }



    @Override

    public boolean nextKeyValue() throws IOException, InterruptedException {



        // 初始化键值对

        key = new Text();

        value = new Text();



        Text temp = new Text();

        if (reader.readLine(temp) == 0)

            return false;

        key.set(temp.getBytes());

        for (int i = 0; i < 2; i++) {

            if (reader.readLine(temp) == 0)

                return false;

            value.append(temp.getBytes(), 0, temp.getLength());

            value.append(new Text(" ").getBytes(), 0, 1);

        }



        return true;

    }



    @Override

    public Text getCurrentKey() throws IOException, InterruptedException {

        return key;

    }



    @Override

    public Text getCurrentValue() throws IOException, InterruptedException {

        return value;

    }



    @Override

    public float getProgress() throws IOException, InterruptedException {

        return 0;

    }



    @Override

    public void close() throws IOException {

        if (reader != null)

            reader.close();

    }



}

// Mapper

public class AutoMapper extends Mapper<Text, Text, Text, Text> {



    public void map(Text key, Text value, Context context) throws IOException, InterruptedException {

        

        context.write(key, value);

        

    }



}

// Driver

public class AutoDriver {



    public static void main(String[] args) throws Exception {

        Configuration conf = new Configuration();

        Job job = Job.getInstance(conf, "JobName");

        job.setJarByClass(cn.tedu.autoinput.AutoDriver.class);

        job.setMapperClass(AutoMapper.class);

        

        job.setInputFormatClass(AutoInputFormat.class);

        



        job.setOutputKeyClass(Text.class);

        job.setOutputValueClass(Text.class);



        FileInputFormat.setInputPaths(job, new Path("hdfs://192.168.32.147:9000/txt/score3.txt"));

        FileOutputFormat.setOutputPath(job, new Path("hdfs://192.168.32.147:9000/result"));



        if (!job.waitForCompletion(true))

            return;

    

    }



}

 

四、多源输入

public class AutoDriver {



    public static void main(String[] args) throws Exception {

        Configuration conf = new Configuration();

        Job job = Job.getInstance(conf, "JobName");

        job.setJarByClass(cn.tedu.autoinput.AutoDriver.class);

        

        



        job.setOutputKeyClass(Text.class);

        job.setOutputValueClass(IntWritable.class);

        

        // 如果多源输入的文件处理格式都一致,可以使用统一的Mapper类

        // 如果多源输入的文件处理格式不一致,则需要分别指定Mapper类

        MultipleInputs.addInputPath(job, new Path("hdfs://192.168.32.147:9000/txt/score.txt"), TextInputFormat.class, AutoMapper1.class);

        MultipleInputs.addInputPath(job, new Path("hdfs://192.168.32.147:9000/txt/score3.txt"), AutoInputFormat.class, AutoMapper2.class);



        FileOutputFormat.setOutputPath(job, new Path("hdfs://192.168.32.147:9000/result2"));



        if (!job.waitForCompletion(true))

            return;

    }



}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鱼鱼大头鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值