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

发布于 2024-08-27 23:09:06 字数 1672 浏览 6 评论 0原文

在调试 Late-hour-out-of-bound-recursive-function 之前:是否有获取子目录的命令? 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放入集合中,向上遍历。不要检查集合中的目录。
  2. 如果到达起始路径,请停止并返回集合。
  3. 重复步骤1和2。

前提:目录结构有限且数据量较小。

Before debugging the late-hour-out-of-bound-recursive-function: is there a command to get 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;
}

Summary about the code:

  1. Go as deep to the directory tree as possible. When there is no dir in a dir, stop, put the dir to the set, traverse up. Do not check dirs in the set.
  2. Stop and return the set if you reach the starting path.
  3. Repeat steps 1 and 2.

PREMISE: the directory-structure is finite and with a small data amount.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

梨涡 2024-09-03 23:09:06

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

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;
}

You can get all subdirs with the following snippet:

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

This gets only immediate subdirs, to retrieve all of them recursively you could write:

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;
}
残花月 2024-09-03 23:09:06

不,Java 标准 API 中没有这样的功能。但有 Apache commons-io;如果您不想将其包含为库,您也可以 看源码

No, there is no such functionality in the Java standard API. But there is in Apache commons-io; if you don't want to include it as a library, you could also look at the source code.

凌乱心跳 2024-09-03 23:09:06

另一个版本没有递归和字母顺序。还使用 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;
    }

Another version with no recursion, and alphabetical order. Also uses a Set to avoid loops (a problem in Unix systems with links).

   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;
    }
小…楫夜泊 2024-09-03 23:09:06

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

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

The sample code above is missing ");" at the end of the statement.
The correct code should be:

  File file = new File("path");
  File[] subdirs = file.listFiles(new FileFilter() {
      public boolean accept(File f) {
          return f.isDirectory();
      }
  });
梦罢 2024-09-03 23:09:06

使用递归:

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();
    }
}

Using recursion:

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();
    }
}
傾城如夢未必闌珊 2024-09-03 23:09:06

这是使用 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));

This is an improved code with Java 8 approach. This code will run on a Recursion basis and find the directories until the last root.

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;
}

If you want only immediate subdirectories list, try with the below line of code..

List<File> subdirs = Arrays.asList(file.listFiles(File::isDirectory));
没企图 2024-09-03 23:09:06
  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 过滤器))

  1. Get all files from root file as array (@see listFiles)
  2. Sort just for directories by distinguishing between files & directories (@see isDirectory)
  3. Convert (filtered) array from step 1 & 2 to list
  4. Add all found directories to resulting list
  5. Repeat that pattern for each directory file you found in step 1, with growing resulting list
  6. At the end, return resulting list

All that put into some lambda magic:

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;
}

Just start with root file (which should be a directory) and an empty list.

Note: Step 1 & 2 can be combined with a filter (@see listFiles(FileFilter filter))

骑趴 2024-09-03 23:09:06
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);
}
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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文