多路输出

多路输出

这个案例的意思是输出结果不是都放在同一个文件里

本案例要求同一个id的 所有商品在同一个目录下,不同id在不同目录下,这些目录都在KeySpilt下

除此之外还需要将所有商品的信息都备份一份放在AllPart目录下

(1)mapper类

package com.simple;

 

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;

import org.apache.hadoop.io.LongWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.Mapper;

public class MultiOutPutMapper extends Mapper<LongWritable, Text, IntWritable, Text> {

    // 每行数据: 1512,iphone5,4英寸,A6处理器,IOS7

//输入:key为行偏移量,value为本行内容

//mapper目的是输出key为id(其实id存储形式用Text或IntWritable自己定都可以的),value为本行内容(即这个产品的所有信息)

    @Override

    protected void map(LongWritable key, Text value, Context context)

            throws IOException, InterruptedException {

        String line = value.toString().trim();

        if(null != line && 0 != line.length()) {

            String[] arr = line.split(",", 2);//最多切两次

            context.write(new IntWritable(Integer.parseInt(arr[0])), value);

        }

    }

}

(2)reducer类

public class MultiOutPutReducer extends Reducer<IntWritable, Text, NullWritable, Text> {

 

    private MultipleOutputs<NullWritable, Text> multipleOutputs = null;

 

    @Override

    protected void setup(Context context) throws IOException, InterruptedException {

        multipleOutputs = new MultipleOutputs<NullWritable, Text>(context);

    }

//多路输出

    @Override

    protected void reduce(IntWritable key, Iterable<Text> values, Context context)

            throws IOException, InterruptedException {

//这都是同一id的

        for(Text text : values) {

//按id分

//目的是:同一个id在同一个子目录,而且这种子目录都放在KeySplit目录里

            // 方法签名:write(String namedOutput, K key, V value, String baseOutputPath)

            multipleOutputs.write("KeySpilt", NullWritable.get(), text, key.toString()+"/");

//输出数据类型:key为NullWritable.get(), value为text

//通用

//AllPart目录是指所有文件还要完整备份在同一个目录

            // 方法签名:write(String namedOutput, K key, V value)

            multipleOutputs.write("AllPart", NullWritable.get(), text);

        }

    }

 

    @Override

    protected void cleanup(Context context) throws IOException, InterruptedException {

        if(null != multipleOutputs) {

            multipleOutputs.close();

            multipleOutputs = null;

        }

    }

 

}

(3)主启动类

package com.simple;

 

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.IntWritable;

import org.apache.hadoop.io.NullWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.Job;

import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import org.apache.hadoop.mapreduce.lib.output.MultipleOutputs;

import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;

  

public class MultiOutPutDriver {

  

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

        Configuration conf = new Configuration();

        Job job = Job.getInstance(conf, "multi-output");

  

        job.setJarByClass(MultiOutPutDriver.class);

  

        job.setMapperClass(MultiOutPutMapper.class);

        job.setMapOutputKeyClass(IntWritable.class);

        job.setMapOutputValueClass(Text.class);

  

        job.setReducerClass(MultiOutPutReducer.class);

        job.setOutputKeyClass(NullWritable.class);

        job.setOutputValueClass(Text.class);//产品信息

  

        FileInputFormat.addInputPath(job, new Path("hdfs://localhost:9000/products.txt"));

  

        // 注意下面这个代码片段

        // 指定第一路输出,名称为"KeySplit",并单独指定该路输出的OutPutFormat类,以及kye和value类型

        MultipleOutputs.addNamedOutput(job, "KeySpilt", TextOutputFormat.class, NullWritable.class, Text.class);

        // 指定第二路输出,名称为"AllPart",并单独指定该路输出的OutPutFormat类,以及kye和value类型

        MultipleOutputs.addNamedOutput(job, "AllPart", TextOutputFormat.class, NullWritable.class, Text.class);

  

        Path outPath = new Path("/multi-output");    // 指定结果输出路径(这两路输出都在这里面)

        FileSystem fs = FileSystem.get(conf);

        if(fs.exists(outPath)) {//注意如果有output文件要先删除

            fs.delete(outPath, true);

        }

        FileOutputFormat.setOutputPath(job, outPath);

  

        job.waitForCompletion(true);

    }

 

}

posted @ 2025-04-07 00:45  Annaprincess  阅读(20)  评论(0)    收藏  举报