hadoop 1.0.4 ,mahout 0.5
首先说明,本篇博客参考:http://blog.csdn.net/wypblog/article/details/17001131 。其次,这里的hadoop版本用处不是很大,虽然使用的是hadoop1.0.4的版本,但是用到的还是之前的JobConf,因为Job设置不了MultipleTextOutputFormat类。具体参考:http://blog.csdn.net/longshenlmj/article/details/9050359 。最后,mahout使用的版本是0.5的,如果要改为0.7的话,代码基本不用变,但是需要引入0.7中的相应路径的类(WeightedVectorWritable的路径0.5和0.7是不一样的)。
需求:把mahout中 kmeans算法算的clusteredPoints文件(这个是对原始数据的分类后的文件)按照不同的类别输出到不同的文件,同一个类别输出到同一个文件。
在hadoop1.0.4,mahout 0.5的环境中需要引入2个jar包,这样在编写代码的时候才不会报错,可以在http://www.docjar.com/jar_detail/commons-cli-2.0-mahout.jar.html https://guava-libraries.googlecode.com/files/guava-r07.zip 下载(不同错误,可能需要找到相应的jar包才行)。
具体代码如下:
MultiFileDriver:
package hadoop.file.multifile;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.FileInputFormat;
import org.apache.hadoop.mapred.FileOutputFormat;
import org.apache.hadoop.mapred.JobClient;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.JobStatus;
import org.apache.hadoop.mapred.SequenceFileInputFormat;
import org.apache.mahout.common.AbstractJob;
import org.apache.mahout.common.HadoopUtil;
/**
* multiple files output driver
* @author fansy
*
*/
public class MultiFileDriver extends AbstractJob {
public static Configuration getMyConf(){
Configuration conf=new Configuration();
conf.set("mapred.job.tracker", "master:9001");
conf.set("fs.default.name","master:9000");
return conf;
}
@Override
public int run(String[] args) throws Exception {
addInputOption();
addOutputOption();
addOption("prefix","pre", "the output file prefix name","prefix");
if (parseArguments(args) == null) {
return -1;
}
Path input = getInputPath();
Path output = getOutputPath();
String prefix=getOption("prefix");
MyMultiOutputFormat.prefix=prefix;
HadoopUtil.delete(MultiFileDriver.getMyConf(), output);
JobConf job=new JobConf(MultiFileDriver.getMyConf(),MultiFileDriver.class);
job.setJobName("output multipul file by input:"+input.getName());
FileInputFormat.setInputPaths(job, input);
FileOutputFormat.setOutputPath(job, output);
job.setMapperClass(MultiMapper.class);
job.setInputFormat(SequenceFileInputFormat.class);
job.setOutputFormat(MyMultiOutputFormat.class);
job.setOutputKeyClass(IntWritable.class);
job.setOutputValueClass(Text.class);
job.setNumReduceTasks(0);
int jobState=JobClient.runJob(job).getJobState();
if(jobState==JobStatus.SUCCEEDED){
return 0;
}
return -1;
}
}
MutiMapper:
package hadoop.file.multifile;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.MapReduceBase;
import org.apache.hadoop.mapred.Mapper;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reporter;
import org.apache.mahout.clustering.WeightedVectorWritable;
/**
* use the old api
* @author fansy
*
*/
public class MultiMapper extends MapReduceBase implements Mapper<IntWritable,WeightedVectorWritable,IntWritable,Text>{
private Text outValue=new Text();
/*@Override
public void map(IntWritable key,WeightedVectorWritable value,Context cxt) throws IOException, InterruptedException{
String vec=value.getVector().asFormatString();
outValue.set(vec);
cxt.write(key, outValue);
}*/
@Override
public void map(IntWritable key, WeightedVectorWritable value,
OutputCollector<IntWritable, Text> output, Reporter reporter)
throws IOException {
String vec=value.getVector().asFormatString();
outValue.set(vec);
output.collect(key, outValue);
}
}
输出格式类:
package hadoop.file.multifile;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.lib.MultipleTextOutputFormat;
public class MyMultiOutputFormat extends MultipleTextOutputFormat<IntWritable, Text> {
public static String prefix ="prefix";
@Override
public String generateFileNameForKeyValue(IntWritable key, Text value,String name){
return prefix+"_"+key.get();
}
}
测试类:
package hadoop.file.multifile;
import org.apache.hadoop.util.ToolRunner;
import org.junit.Test;
import junit.framework.TestCase;
public class MultiFileDriverTest extends TestCase {
@Test
public void testRun() throws Exception{
String[] args={"-i","/user/Administrator/output/clusteredPoints/part-m-00000",
"-o","/user/fansy/multi/01"};
// String[] args={"-i","aa"};
ToolRunner.run(MultiFileDriver.getMyConf(), new MultiFileDriver(), args);
}
}
测试输出不同文件截图如下:
把输入参数增加一个 -pre center,然后再次进行测试,发现输出文件的前缀并不是center,还是prefix,说明在MyMultiOutputFormat中设置static变量没有作用;这里其实主要是想实现可定制前缀的设计思路。这种思路不行的话,可以考虑使用文件的方式,即得到prefix变量之后把其写入hdfs中的一个文件,然后在MyMultiOutputFormat中把其读取出来进行赋值,这样应该是ok的。
如果您觉得lz的blog或者资源还ok的话,可以选择给lz投一票,多谢。(投票地址:http://vote.blog.csdn.net/blogstaritem/blogstar2013/fansy1990 )
分享,成长,快乐
转载请注明blog地址:http://blog.csdn.net/fansy1990