使用Spark在hdfs中递归搜索所有文件名

时间:2019-02-21 07:58:45

标签: scala apache-spark hadoop

我一直在寻找一种在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”不阅读文本本身(有点像转换仅在一个动作之后发生,而某些“命令”却从未真正发生过)。

非常感谢您!

1 个答案:

答案 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
}

就这样。它已成功测试。您可以按原样使用。.