我试图递归地遍历给定目录及其所有子目录,并列出所有以.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文件。所以我知道它们存在,我无法使过滤器正常工作。
答案 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