在我的输入目录中,我有一个要处理的文件列表以及一个元数据文件。在输出缩减器方面,我想索引到此文件,并将额外的元数据添加到输出中。如何获取输入目录?
在旧的API中,可以这样做:
context.getConfiguration().get("map.input.dir")
新的API允许映射器执行以下操作:
(FileSplit)context.getInputSplit()).getPath()
但是Reducer上下文没有此功能。此外,对于简单的任务来说,加入似乎有些过头了。
Reducer
在Mappers
的输出上运行,因此Context
中没有关于输入文件的信息。现在,要识别reduce
中的输入目录,只需要使用共享的代码标记map
中的outValue,加入在这里无关紧要。例如:
MAP
String tag = (FileSplit)context.getInputSplit()).getPath()
.getParent().getName().toString();
context.write(outKey, new Text(tag + "_" + value.toString));
如果您对fileName本身感兴趣(事实上应该是这样),请删除getParent()
调用。
减少
String metaFileName = "meta.dat";
for(Text value : values){
String[] tagVal = value.toString().split("_",2);
if(strVal[0].equals(metaFileName){
// process the meta file here // strVal[1] contains the actual value
} else { // process data files }
}
这应该能解决你的问题。这里的一个建议是,您可以利用MultiOutputs
api从reducer写入不同类型的文件。否则,在工作结束后,将很难识别metaFile(它将分布在几个输出文件中)。
MapReduce作业的输入由FileInputFormat.addInputPath()
方法指定。正如方法名称所暗示的,addInputPath()
方法可以被多次调用,以指定其他文件和/或目录作为MapReduce作业的输入。因此,可能存在多个路径作为单个MapReduce作业的输入。
映射器任务在单个拆分上操作。因此,Mapper能够检索正在处理的特定分割的路径是有意义的。
然而,Reducer通常对多个映射器的输出进行操作,这些映射器的输入拆分可能(可能)具有不同的路径。因此,在Reducer中没有InputSplit的概念,这就是为什么你无法获得它的路径