递归列出文件并按扩展名过滤

时间:2019-11-27 19:15:53

标签: scala apache-spark

我试图递归地遍历给定目录及其所有子目录,并列出所有以.json结尾的文件。多亏了this answer,我才有了递归功能。现在,我试图找出过滤部分。

这是我当前的尝试:

Node Type2() :
{ Node t1; }
{
  "Nat" { return new Node("Nat", null, null); }
| "Bool" { return new Node("Bool", null, null); }
| "(" t1=Type() ")" { return t1; }
}

Node Type() :
{ Node t1; Node t2; }
{
  t1=Type2() ( " -> " t2=Type() { return new Node("->", t1, t2); } )? { return t1; }
}

这将返回一个空列表。如果我使用没有过滤器的listStatus行,它将返回我传递的路径中所有文件的列表,包括所有* .json文件。所以我知道它们存在,我无法使过滤器正常工作。

1 个答案:

答案 0 :(得分:3)

问题是首先应用筛选器以筛选出子目录。将过滤器向下移至flatMap。

import org.apache.hadoop.fs.{FileSystem, Path}

val fs = FileSystem.get(spark.sparkContext.hadoopConfiguration)

def listJsonFiles(hdfsPath: String): List[String] = {
  fs
    .listStatus(new Path(hdfsPath))
    //.listStatus(new Path(hdfsPath))
    .flatMap { obj =>
      if (obj.isDirectory) listJsonFiles(obj.getPath.toString)
      else if(obj.getPath.getName.endsWith(".json")) List(obj.getPath.toString)
      else Nil
    }
    .toList
}
val files = listJsonFiles("/var/tmp/stuff")
files.foreach(println)

文件系统上有本机方法来递归扫描HDFS目录。

FileSystem.listFiles接受一个参数以进行递归搜索并返回RemoteIteator,我们可以用它来过滤所需的文件。这也可以保护从OOO运行的JVM。

import org.apache.hadoop.fs.{FileSystem, Path, RemoteIterator}

val fs = FileSystem.get(spark.sparkContext.hadoopConfiguration)

// implicit for converting remote Iterator to scala iterator
implicit def  remoteIteratorToIterator[A](ri: RemoteIterator[A]): Iterator[A] = new Iterator[A] {
  override def hasNext: Boolean = ri.hasNext

  override def next(): A = ri.next()
}

def listJsonFiles(hdfsPath: String): List[String] = {
  fs
    .listFiles(new Path(hdfsPath), true)
    .map(_.getPath.toString)
    .filter(_.endsWith(".json"))
    .toList
}
val files = listJsonFiles("/var/tmp/stuff")
files.foreach(println)

输入目录

$ tree stuff/
stuff/
├── dir1
│   ├── dir1.json
│   └── dir2
│       └── dir2.json
└── stuff.json

2 directories, 3 files

输出

file:/var/tmp/stuff/stuff.json
file:/var/tmp/stuff/dir1/dir2/dir2.json
file:/var/tmp/stuff/dir1/dir1.json