为目录和子目录中的每个文件执行某些操作

时间:2016-01-09 22:55:20

标签: java file

我需要在文件列表中应用更复杂的逻辑。具体来说,在应用软件更新时,我想对从更新zip存档获取的文件执行此操作:

  • updateFile成为更新存档中的文件,originalFile是当前版本文件,backupFile是原始文件的备份
  • 如果originalFile与当前正在运行的jar文件相同,请跳过
  • 如果updateFile的父目录是特定名称,请跳过它(例如,带有用户数据的目录)

我希望有一些选项,例如为每个文件运行回调:

GreatFileLibrary.forEveryChildOf(new File("my path"), 
                                (File child)->{ ... logic here ... });

如果不是这样,那么至少只需获取某些Collection中的所有文件并循环播放它:

Iterable<File> files = GreatFileLibrary.listChildren(new File("my path"));
for(File child:files) {
    ... logic ...
}

前者允许我显示进度(感谢知道列表长度)但我坦率地假设更新几乎是即时的。

文件当然可以返回一些孩子的列表,所以超级天真的方法是:

  /** Returns list of all child files, recursively. **/
  public static Iterable<File> listFileChildren(File parent, ArrayList<File> list) {
    File[] files = parent.listFiles();
    for(File file:files) {
      list.add(file);
      if(file.isDirectory())
        listFileChildren(file, list);
    }
    return list;
  }
  public static Iterable<File> listFileChildren(File parent) {
    return listFileChildren(parent, new ArrayList());
  }

内置Java 8库能做得更好吗?我的快速代码有缺陷吗?我会真的感谢您删除File[]转换为Iterable<File>,就像我的代码一样,这很脏。

4 个答案:

答案 0 :(得分:2)

代码中的列表创建将耗费大量时间,因此请尽量避免使用它。 一个简单的方法是:

public void forEveryChildOf(File file) {
    for(File child:file.listFiles())
        doForEach(file,child);
}

private void doForEach(File topParent,File child){
    if(child.isFile())
        System.out.println("Do logic");

    if(child.isDirectory())
        for(File subchild:child.listFiles())
            doForEach(topParent,subchild);
}

答案 1 :(得分:1)

如果您不介意创建多个流的性能影响,此函数将返回目标文件夹中每个子项的流。

以下版本使用了Java 7的{​​{1}}和Files类,因此您可能需要重写某些内容(或调用Path

Path#toFile

此版本使用普通的public static Stream<Path> stream(Path path) { try { return Files.isDirectory(path) ? Files.list(path).map(innerpath -> stream(innerpath)).flatMap(s -> s) : Stream.of(path); } catch (IOException e) { throw new RuntimeException(e); } } s

File

您可以在最终public static Stream<File> stream(File file) { return file.isDirectory() ? Arrays.stream(file.listFiles()).map(innerfile -> stream(innerfile)).flatMap(s -> s) : Stream.of(file); } 收集List或致电forEach

答案 2 :(得分:0)

public void allFiles(File raiz) {          
   for (File arquivo : raiz.listFiles(filtro)) {
      if (arquivo.isFile()) {
          try {              
            System.out.println(arquivo);
          } catch (Exception e) {
            System.out.println("erro" +arquivo);
          }
      } else {
         allFiles(arquivo);
      } 
   }
}

答案 3 :(得分:0)

来自nio的

FileVisitor

    Path startPath = new File("...").toPath();
    Files.walkFileTree(startPath, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                throws IOException {
            //your logic

            return FileVisitResult.CONTINUE;
        }
    });