自定义InputFormat实现小文件的合并

需求

无论hdfs还是mapreduce,对于小文件都有损效率,实践中,又难免面临处理大量小文件的场景,此时,就需要有相应解决方案


将文件的路径作为key,文件的内容作为值输出

分析

  • 小文件的优化无非以下几种方式:
    1、在数据采集的时候,就将小文件或小批数据合成大文件再上传HDFS
    2、在业务处理之前,在HDFS上使用mapreduce程序对小文件进行合并
    3、在mapreduce处理时,可采用combinelnputFormat提高效率

代码的实现

InputFormat部分

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.BytesWritable;
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;

import java.io.IOException;

public class MyInputFormat extends FileInputFormat<Text, BytesWritable> {
    @Override
    protected boolean isSplitable(JobContext context, Path filename) {
        return false;
    }

    public RecordReader createRecordReader(InputSplit inputSplit, TaskAttemptContext taskAttemptContext) throws IOException, InterruptedException {
        return new MyRecordReader();
    }
}

在这里插入图片描述

RecoreReader部分

import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.BytesWritable;
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;

import java.io.IOException;

public class MyRecordReader extends RecordReader<Text, BytesWritable> {
    Text k = new Text();
    BytesWritable v = new BytesWritable();
    FileSplit fs = new FileSplit();
    FSDataInputStream inputStream;
    boolean flag = true;

    public void initialize(InputSplit inputSplit, TaskAttemptContext taskAttemptContext) throws IOException, InterruptedException {
        fs = (FileSplit) inputSplit;
        Path path = fs.getPath();
        FileSystem fileSystem = path.getFileSystem(taskAttemptContext.getConfiguration());
        inputStream = fileSystem.open(path);
    }

    public boolean nextKeyValue() throws IOException, InterruptedException {
        if (flag) {
            k.set(fs.getPath().toString());
            byte[] buf = new byte[(int) fs.getLength()];
            inputStream.read(buf);
            v.set(buf, 0, buf.length);
            flag = false;
            return true;
        } else {
            return false;
        }
    }

    public Text getCurrentKey() throws IOException, InterruptedException {
        return k;
    }

    public BytesWritable getCurrentValue() throws IOException, InterruptedException {
        return v;
    }

    public float getProgress() throws IOException, InterruptedException {
        return 0;
    }

    public void close() throws IOException {
        inputStream.close();
    }
}

在这里插入图片描述

Driver阶段需要的操作

job.setInputFormatClass(MyInputFormat.class);
  • 一定要加上这句话,使用自定义InputFormat!!!
  • 一定要加上这句话,使用自定义InputFormat!!!
  • 一定要加上这句话,使用自定义InputFormat!!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值