我正在尝试读取目录中的文件,其路径被指定为MapReduce程序的参数。目的是对每个文件执行一些计算(比如特定单词的出现次数)。此外,文件的名称必须与模式匹配(例如.java文件)。程序的输出是文件的名称以及计算的值。
到目前为止,我已经能够实现一个非常基本的Map程序,该程序在没有任何特定模式的情况下读取目录的内容,并输出文件名和常数。映射器代码看起来像这样
public class CCMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
private static IntWritable complexityCount = new IntWritable(1);
private Text result = new Text();
public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException
{
String fileName = ((FileSplit) context.getInputSplit()).getPath().getName();
result.set(filePathString);
context.write(result, complexityCount);
}
}
输入目录有3个文件 - file1,file2,file3。但是这个程序的输出看起来像这样
file1.txt 1
file1.txt 1
file1.txt 1
file1.txt 1
file1.txt 1
file1.txt 1
file1.txt 1
file2.txt 1
file2.txt 1
file2.txt 1
file2.txt 1
file3.txt 1
如何让程序为每个文件输出一次。还有一种方法可以一次读取一个文件,对该文件执行计算并输出文件名和结果吗?如何修改InputSplit的值以匹配每个特定文件的大小?
答案 0 :(得分:1)
我理解您的代码正在读取每个文件的内容。 File1必须有7行,因此每行的键值对为“File1.txt 1”一次。 类似地,File2.txt必须有4行而File3.txt是1行。
要输出每个文件的一个匹配项,您必须在reduce函数中编写代码,以便根据键总结值。
public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable> {
@Override
public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable value : values) {
sum += value.get();
}
context.write(key, new IntWritable(sum));
}
}