我正在使用递归函数遍历根目录下的文件。我只想提取*.txt
个文件,但我不想排除目录。现在我的代码看起来像这样:
val stream = Files.newDirectoryStream(head, "*.txt")
但是通过这样做,它将不匹配任何目录,并且iterator()
返回的是False
。我正在使用Mac,因此我不想包含的噪音文件是.DS_STORE
。如何让newDirectoryStream
获取*.txt
的目录和文件?有办法吗?
答案 0 :(得分:5)
你真的应该使用FileVisistor
,它使代码变得如此简单:
import java.nio.file.attribute.BasicFileAttributes
import java.nio.file._
import scala.collection.mutable.ArrayBuffer
val files = ArrayBuffer.empty[Path]
val root = Paths.get("/path/to/your/directory")
Files.walkFileTree(root, new SimpleFileVisitor[Path] {
override def visitFile(file: Path, attrs: BasicFileAttributes) = {
if (file.getFileName.toString.endsWith(".txt")) {
files += file
}
FileVisitResult.CONTINUE
}
})
files.foreach(println)
答案 1 :(得分:1)
不确定是否需要nio。如果不是,这很简单,似乎可以完成这项工作。并且没有可变的集合:)
import java.io.File
def collectFiles(dir: File) = {
def collectFilesHelper(dir: File, soFar: List[String]): List[String] = {
dir.listFiles.foldLeft(soFar) { (acc: List[String], f: File) =>
if (f.isDirectory)
collectFilesHelper(f, acc)
else if (f.getName().endsWith(".txt"))
f.getCanonicalPath() :: acc
else acc
}
}
collectFilesHelper(dir, List[String]())
}
答案 2 :(得分:0)
好吧,我实际上并没有使用FileVisitor
,但使用它应该很好。我使用了递归并保留了两个列表:一个是用于跟踪目录的原始文件列表,另一个列表用于存储实际的*.txt
文件:
@tailrec
def recursiveTraverse(filePaths: ListBuffer[Path], resultFiles: ListBuffer[Path]): ListBuffer[Path] = {
if (filePaths.isEmpty) resultFiles
else {
val head = filePaths.head
val tail = filePaths.tail
if (Files.isDirectory(head)) {
val stream: Try[DirectoryStream[Path]] = Try(Files.newDirectoryStream(head))
stream match {
case Success(st) =>
val iterator = st.iterator()
while (iterator.hasNext) {
tail += iterator.next()
}
case Failure(ex) => println(s"The file path is incorrect: ${ex.getMessage}")
}
stream.map(ds => ds.close())
recursiveTraverse(tail, resultFiles)
}
else{
if (head.toString.contains(".txt")) {
recursiveTraverse(tail, resultFiles += head)
}else{
recursiveTraverse(tail, resultFiles)
}
}
}
}
但是,这不是最好的解决方案,但对我的具体问题来说是最简单的。如果你想这样做,请显示一个更短的FileVisitor
代码:)