2016-03-29 96 views
0

我想申请一个功能在目录和子目录中的每个文件,内容如下:阶流处理递归文件和子目录

def applyRecursively(dir: String, fn: (File) => Any) { 
    def listAndProcess(dir: File) { 
     dir.listFiles match { 
     case null => out.println("exception: dir cannot be listed: " + dir.getPath); List[File]() 
     case files => files.toList.sortBy(_.getName).foreach(file => { 
      fn(file) 
      if (file.isDirectory) listAndProcess(file) 
     }) 
     } 
    } 
    listAndProcess(new File(dir)) 
    } 

    def exampleFn(file: File) { println(s"processing $file") } 

    applyRecursively(dir, exampleFn) 

这个工程。以前他们answered如何通过使用scala迭代器来重构此代码。这里的问题是我如何通过使用scala Streams来重构此代码。 是这样的:

val stream: Stream[File] = ... // ??? 
stream.foreach(exampleFn) 
+0

'应用功能,每个文件' - 为每个文件或每个文件有或子目录?应该在子目录上调用'fn(file)'? –

回答

3

在这里你去:

def fileStream(dir: File): Stream[File] = 
    Option(dir.listFiles).map(_.toList.sortBy(_.getName).toStream).map { 
    files => files.append(files.filter(_.isDirectory).flatMap(fileStream)) 
    } getOrElse { 
    println("exception: dir cannot be listed: " + dir.getPath) 
    Stream.empty 
    } 

更新:以上回报文件和目录执行。下面是如何有效地排除目录:

def fileStreamNoDirs(dir: File): Stream[File] = 
    Option(dir.listFiles).map(_.toList.sortBy(_.getName).toStream.partition(_.isDirectory)) 
    .map { case (dirs, files) => 
     files.append(dirs.flatMap(fileStreamNoDirs)) 
    } getOrElse { 
    println("exception: dir cannot be listed: " + dir.getPath) 
    Stream.empty 
    } 

然而,简单fileStream("/some/path").filterNot(_.isDirectory)会做同样的工作。

UPDATE2:这种变体保留了原来的例子的遍历顺序:

def fileStream(dir: File): Stream[File] = 
    if (dir.isDirectory) 
    Option(dir.listFiles) 
     .map(_.toList.sortBy(_.getName).toStream.flatMap(file => file #:: fileStream(file))) 
     .getOrElse { 
     println("exception: dir cannot be listed: " + dir.getPath) 
     Stream.empty 
     } 
    else Stream.empty 
+0

是不是将子目录本身包含到文件列表中?当然,话题标题的原始代码也会在目录中调用'fn',但是他的问题文本表明这不是他的意图。...... –

+1

@ Arioch'The,好点。更新。 – Aivean

+0

是的,我想包括子目录到文件列表中,如提供的代码。对于问题的文本抱歉。 –