多路输出
多路输出
这个案例的意思是输出结果不是都放在同一个文件里
本案例要求同一个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);
}
}

浙公网安备 33010602011771号