Java:如何递归获取所有子目录?

时间:2010-04-05 21:01:12

标签: java recursion filesystems subdirs

在调试延迟时间外的递归函数之前:是否有一个获取子目录的命令? giveMeSubDirs(downToPath)

// WARNING: RECURSION out of bound or too much data
public HashSet<FileObject> getAllDirs(String path) {
  HashSet<FileObject> checkedDirs = new HashSet<FileObject>();
  HashSet<FileObject> allDirs = new HashSet<FileObject>();

  String startingPath = path;

  File fileThing = new File(path);
  FileObject fileObject = new FileObject(fileThing);

  for (FileObject dir : getDirsInDir(path)) {

    // SUBDIR

    while ( !checkedDirs.contains(dir) 
        && !(getDirsInDir(dir.getFile().getParent()).size() == 0)) {

      // DO NOT CHECK TOP DIRS if any bottom dir UNCHECKED!

      while ( uncheckedDirsOnLevel(path, checkedDirs).size() > 0) { 

        while (getDirsInDir(path).size() == 0 
            || (numberOfCheckedDirsOnLevel(path, checkedDirs)==getDirsInDir(path).size())) {
          allDirs.add(new FileObject(new File(path)));
          checkedDirs.add(new FileObject(new File(path)));

          if(traverseDownOneLevel(path) == startingPath )
            return allDirs;

          //get nearer to the root
          path = traverseDownOneLevel(path);
        }
        path = giveAnUncheckedDir(path, checkedDirs);

        if ( path == "NoUnchecked.") {
          checkedDirs.add(new FileObject( (new File(path)).getParentFile() ));
          break;
        }
      }
    }
  }
  return allDirs;
}

有关代码的摘要:

  1. 尽可能深入目录树。当dir中没有dir时,停止,将dir放到set中,然后向上移动。不要检查套装中的dirs。
  2. 如果到达起跑路径,请停止并返回该组。
  3. 重复步骤1和2.
  4. PREMISE:目录结构是有限的,数据量很小。

8 个答案:

答案 0 :(得分:24)

您可以使用以下代码段获取所有子目录:

File file = new File("path");
File[] subdirs = file.listFiles(new FileFilter() {
    public boolean accept(File f) {
        return f.isDirectory();
    }
});

这只会立即获得子目录,以递归方式检索所有这些子句:

List<File> getSubdirs(File file) {
    List<File> subdirs = Arrays.asList(file.listFiles(new FileFilter() {
        public boolean accept(File f) {
            return f.isDirectory();
        }
    }));
    subdirs = new ArrayList<File>(subdirs);

    List<File> deepSubdirs = new ArrayList<File>();
    for(File subdir : subdirs) {
        deepSubdirs.addAll(getSubdirs(subdir)); 
    }
    subdirs.addAll(deepSubdirs);
    return subdirs;
}

答案 1 :(得分:2)

不,Java标准API中没有此类功能。但有Apache commons-io;如果您不想将其作为库包含,则还可以look at the source code

答案 2 :(得分:2)

另一个没有递归和字母顺序的版本。还使用Set来避免循环(带有链接的Unix系统中的问题)。

   public static Set<File> subdirs(File d) throws IOException {
        TreeSet<File> closed = new TreeSet<File>(new Comparator<File>() {
            @Override
            public int compare(File f1, File f2) {
                return f1.toString().compareTo(f2.toString());
            }
        });
        Deque<File> open = new ArrayDeque<File>();
        open.push(d);
        closed.add(d);
        while ( ! open.isEmpty()) {
            d = open.pop();
            for (File f : d.listFiles()) {
                if (f.isDirectory() && ! closed.contains(f)) {
                    open.push(f);
                    closed.add(f);
                }
            }
        }
        return closed;
    }

答案 3 :(得分:1)

上面的示例代码缺少“);”在声明的最后。 正确的代码应该是:

  File file = new File("path");
  File[] subdirs = file.listFiles(new FileFilter() {
      public boolean accept(File f) {
          return f.isDirectory();
      }
  });

答案 4 :(得分:0)

使用递归:

private void getAllSubFoldersInPath(File path)
{
    File[] files=path.listFiles();
    try {
        for(File file: files)
        {
            if(file.isDirectory())
            {
                System.out.println("DIRECTORY:"+file.getCanonicalPath());
                getAllSubFoldersInPath(file);
            }
            else
            {
                System.out.println("FILE: "+file.getCanonicalPath());   
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

答案 5 :(得分:0)

这是Java 8方法的改进代码。该代码将基于递归运行,并找到目录直到最后一个根。

List<File> findAllSubdirs(File file) {
    List<File> subdirs = Arrays.asList(file.listFiles(File::isDirectory));
    subdirs = new ArrayList<File>(subdirs);

    List<File> deepSubdirs = new ArrayList<File>();
    for(File subdir : subdirs) {
        deepSubdirs.addAll(findAllSubdirs(subdir)); 
    }
    subdirs.addAll(deepSubdirs);
    return subdirs;
}

如果只需要直接子目录列表,请尝试以下代码行。

List<File> subdirs = Arrays.asList(file.listFiles(File::isDirectory));

答案 6 :(得分:0)

  1. 从根文件中获取所有文件作为数组(@see listFiles
  2. 通过区分文件和目录(@see isDirectory)仅对目录进行排序
  3. 将步骤1和2中的(过滤后的)数组转换为列表
  4. 将所有找到的目录添加到结果列表中
  5. 为您在步骤1中找到的每个目录文件重复该模式,并增加结果列表
  6. 最后,返回结果列表

所有进入lambda魔术的东西:

private static List<File> getAllSubDirectories(File root, List<File> result) {
    List<File> currentSubDirs = Arrays.asList(Objects.requireNonNull(root.listFiles(File::isDirectory), "Root file has to be directory"));
    result.addAll(currentSubDirs);
    currentSubDirs.forEach(file -> getAllSubDirectories(file, result));
    return result;
}

只需从根文件(应该是目录)和一个空列表开始。

注意:第1步和第2步可以与过滤器结合使用(@see listFiles(FileFilter filter)

答案 7 :(得分:-1)

class DirFileFilter extends FileFilter {
  boolean accept(File pathname) {
    return pathname.isDirectory();
  }
}

DirFileFilter filter = new DirFileFilter();
HashSet<File> files = new HashSet<File>();

void rec(File root) {
  // add itself to the list
  files.put(root);
  File[] subdirs = root.list(filter);

  // bound of recursion: must return 
  if (subdirs.length == 0)
    return;
  else //this is the recursive case: can call itself
    for (File file : subdirs)
      rec(file);
}