最新版本的Hadoop已经可以使用FileInputFormat.setInputDirRecursive
轻松支持嵌套输入目录,它依赖于mapreduce.input.fileinputformat.input.dir.recursive
配置密钥。
还可以使用MultipleInputs.addInputPath
指定多个映射器/输入目录组合。
但我可以同时做两件事吗?换句话说,有没有办法指定多个映射器/输入目录组合,其中输入目录是递归包含的?
一个具体的例子: 我有以下目录结构:
/dataset1/subdir1/data1.txt
/dataset2/subdir2/data2.txt
我试过这样的事情:
Job job = Job.getInstance(conf);
FileInputFormat.setInputDirRecursive(job, true);
MultipleInputs.addInputPath(job, new Path("/dataset1"), TextInputFormat.class,
Mapper1.class);
MultipleInputs.addInputPath(job, new Path("/dataset2"), TextInputFormat.class,
Mapper2.class);
...
job.waitForCompletion(true);
但是我在Error: java.io.IOException: 's3://bucketname/dataset1/subdir1' is a directory
这是在Hadoop 2.4.0下的Amazon EMR中运行。
编辑:Hadoop版本是2.4.0,而不是2.6.0
答案 0 :(得分:1)
嗯,不确定s3,但这是正常的。应指向文件而不是目录。
试试这个。
方法1
final static public void addInputPathRecursively(FileSystem fs, Path path, PathFilter inputFilter, Job job,boolean swithc) throws IOException
{
for (FileStatus stat : fs.listStatus(path, inputFilter))
{
if (stat.isDirectory())
{
addInputPathRecursively(fs, stat.getPath(), inputFilter, job);
} else
{
if (swithc)
{
MultipleInputs.addInputPath(job, new Path(stat.getPath().toString()), TextInputFormat.class, Mapper1.class);
} else
MultipleInputs.addInputPath(job, new Path(stat.getPath().toString()), TextInputFormat.class, Mapper2.class);
}
}
}
在驱动程序类中,您可以相应地调用它。
addInputPathRecursively(fs, datset1path, new FileFilter(conf, fs,
new String[] { txt }), job,true);
addInputPathRecursively(fs, datset2path, new FileFilter(conf, fs,
new String[] { txt }), job,false);
这是一个示例,但是如果要应用regEx,则可以正常控制pathfilter。
方法2 设置这个也应该是神奇的。
FileInputFormat.setInputDirRecursive(job,true);
方法3 绕过映射器并在线级处理。 (不是个好主意!)