我正在尝试编写一个MapReduce作业,该作业需要多个分隔的输入源。所有来源都包含相同的信息,但它可能位于不同的列中,并且每个来源的分隔符可能不同。通过配置文件在映射器中解析源。此配置文件允许用户限制这些不同的分隔符和列映射。
例如,使用配置属性
解析input1input1.separator=,
input1.id=1
input1.housename=2
input1.age=15
其中1,2和15是input1中与这些属性相关的列。
因此,映射器需要知道每个输入源使用哪些配置属性。我无法对此进行硬编码,因为其他人将会运行我的工作,并希望在不需要编译器的情况下添加新输入。
显而易见的解决方案是从拆分中提取文件名并以这种方式应用配置。
例如,假设我输入了两个文件," source1.txt"和" source2.txt"。我可以编写像
这样的配置source1.separator=,
source1.id=2
...
source2.separator=|
source2.id=4
...
映射器将从拆分中获取文件名,然后使用相同的前缀读取配置属性。
但是,如果我指向Hive仓库中的文件夹,我就无法使用它。我可以提取一些路径并使用它们,但我并不觉得这是一个优雅或坚固的解决方案。有更简单的方法吗?
答案 0 :(得分:0)
我已经解决了。事实证明,维护了将输入源(文件或目录)添加到FileInputFormat
的顺序,然后将其作为mapreduce.input.fileinputformat.inputdir
存储在作业上下文中。所以,我的解决方案
<强> Runner.java 强>
for(int i=X; i<ar.length; i++) {
FileInputFormat.addInputPath(job, new Path(ar[i]));
}
其中 X 是可以找到输入路径的第一个整数。
<强> InputMapper.java 强>
#Get the name of the input source in the current mapper
Path filePath = ((FileSplit) context.getInputSplit()).getPath();
String filePathString = ((FileSplit) context.getInputSplit()).getPath().toString();
#Get the ordered list of all input sources
String pathMappings = context.getConfiguration()
.get("mapreduce.input.fileinputformat.inputdir");
我知道输入源添加到作业的顺序,然后我可以让用户使用数字设置配置属性,并将数字映射到CLI中将作业输入源添加到作业的顺序。
答案 1 :(得分:0)
我不确定MultipleInputs
是否提供PathFilter
整合。但是,您可以根据您的条件扩展一个并将匹配的文件提供给不同的Mapper
类型。
FileStatus[] csvfiles = fileSystem.listStatus(new Path("hive/path"),
new PathFilter() {
public boolean accept(Path path) {
return (path.getName().matches(".*csv$"));
}
});
将处理映射器分配给此列表:
MultipleInputs.addInputPath(job, csvfiles[i].getPath(),
YourFormat.class, CsvMapper.class);
对于每种文件类型,您必须提供所需的正则表达式。希望你擅长它。