我正在处理一个嵌套目录结构的工作,其中包含多个级别的文件:
one/
├── three/
│ └── four/
│ ├── baz.txt
│ ├── bleh.txt
│ └── foo.txt
└── two/
├── bar.txt
└── gaa.txt
当我将one/
添加为输入路径时,不会处理任何文件,因为没有文件在根级别立即可用。
我读过关于job.addInputPathRecursively(..)
,但这似乎在最近的版本中已被弃用(我使用的是 hadoop1.0.2)。我编写了一些代码来遍历文件夹并使用 job.addInputPath(dir)
添加每个目录,直到由于某种原因尝试将目录处理为输入文件时作业崩溃,例如 - 尝试fs.open(split.getPath())
,当split.getPath()
是一个目录时(这发生在LineRecordReader.java
内部)。
我试图说服自己,必须有一种更简单的方法来为具有嵌套目录结构的作业提供。有什么想法吗?
编辑 - 显然有一个开放的错误。
我没有找到任何关于此的文档,但*/*
工作。所以它-input 'path/*/*'
.
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
FileInputFormat.setInputDirRecursive(job, true);
不用了,谢谢,叫我雷锋就行了!
我发现递归浏览数据可能很危险,因为可能存在来自distcp
或类似内容的滞留日志文件。让我提出一个替代方案:
在命令行上执行递归遍历,然后将空格分隔参数中的路径传入MapReduce程序。从argv
中获取列表:
$ hadoop jar blah.jar "`hadoop fs -lsr recursivepath | awk '{print $8}' | grep '/data.*.txt' | tr 'n' ' '`"
很抱歉长时间的打击,但它完成了工作。您可以将内容包装在 bash 脚本中以将其分解为变量。
我个人喜欢通过文件路径方法来编写我的mapreduce作业,因此代码本身没有硬编码路径,并且我相对容易将其设置为针对更复杂的文件列表运行。
不知道是否仍然相关,但至少在 hadoop 2.4.0 中,您可以将属性 mapreduce.input.fileinputformat.input.dir.recursive 设置为 true,它将解决您的问题。
只需使用 FileInputFormat.addInputPath("with file pattern");我正在编写我的第一个用于图形分析的 Hadoop 程序,其中输入来自 .gz格式的 diff dir ......它对我有用!!