我一直在寻找一种在Hadoop文件系统(hdfs)中的目录及其子目录中获取所有 文件名 的方法。 / p>
我发现我可以使用这些命令来获取它:
sc.hadoopConfiguration.set("mapreduce.input.fileinputformat.input.dir.recursive", "true")
sc.wholeTextFiles(path).map(_._1)
这是“ wholeTextFiles”文档:
从HDFS,本地文件系统(在所有节点上都可用)或任何Hadoop支持的文件系统URI中读取文本文件目录。每个文件都作为一条记录读取,并以键值对的形式返回,其中键是每个文件的路径,值是每个文件的内容。
参数:
path-输入数据文件的目录,路径可以是 逗号分隔的路径作为输入列表。
minPartitions-A 输入数据的最小分割数的建议值。
返回:
RDD表示文件路径的元组和相应的 文件内容
注意:首选小文件,大文件也是 允许,但可能会导致性能下降。,在某些文件系统上, ... / path / *可能是一种更有效的方式来读取文件中的所有文件 目录而不是... / path /或... / path,分区是 由数据位置决定。这可能导致分区过少 默认。
如您所见,“ wholeTextFiles”将返回一个RDD,其中包含文件名及其内容。因此,我尝试映射它并仅获取文件名,但我怀疑它仍会读取文件。
我怀疑是这样的原因:例如,如果我尝试计算(例如),并且得到“内存不足”的火花(丢失执行程序并且无法完成任务)。
我宁愿使用Spark来尽可能快地实现此目标,但是,如果还有其他具有合理性能的方法,我很乐意尝试一下。
编辑: 要清除它-我想使用Spark来做,我知道我可以使用HDFS命令和类似的东西来做-我想知道如何使用Spark随附的现有工具来做这件事,也许还可以解释一下使“ wholeTextFiles”不阅读文本本身(有点像转换仅在一个动作之后发生,而某些“命令”却从未真正发生过)。
非常感谢您!
答案 0 :(得分:1)
这种方法可以列出所有文件,直到最后一个子目录的深度。...并且不使用wholetextfiles
并且是递归调用,直到子目录的深度...
val lb = new scala.collection.mutable[String] // variable to hold final list of files
def getAllFiles(path:String, sc: SparkContext):scala.collection.mutable.ListBuffer[String] = {
val conf = sc.hadoopConfiguration
val fs = FileSystem.get(conf)
val files: RemoteIterator[LocatedFileStatus] = fs.listLocatedStatus(new Path(path))
while(files.hasNext) {// if subdirectories exist then has next is true
var filepath = files.next.getPath.toString
//println(filepath)
lb += (filepath)
getAllFiles(filepath, sc) // recursive call
}
println(lb)
lb
}
就这样。它已成功测试。您可以按原样使用。.