Java:如何只获得某个级别的子目录名称?

时间:2016-12-27 11:21:37

标签: java directory-structure

这是我的文件夹结构:

parent/
  child1/
    child1.1/
    child1.2/
  child2/
    child 2.1/
    child 2.2/
  child3/
    child 3.1/
    child 3.2/

如何仅提取第三级文件夹的名称? (我还没能在网上找到这个)

输出应为:

child1.1 ,child1.2 
child2.1 ,child2.2
child3.1 ,child3.2

我引用了Java: how to get all subdirs recursively?来查找子目录。

7 个答案:

答案 0 :(得分:2)

要使level参数化我建议代码:

static public List<File> getDirs(File parent, int level){
    List<File> dirs = new ArrayList<File>();
    File[] files = parent.listFiles();
    if (files == null) return dirs; // empty dir
    for (File f : files){
        if (f.isDirectory()) {
             if (level == 0) dirs.add(f);
             else if (level > 0) dirs.addAll(getDirs(f,level-1));
        }
    }
    return dirs;
}

并称之为:

List<File> l = getDirs(new File("/some/path"), 3);

编辑:我在空目录

的情况下添加了验证

答案 1 :(得分:1)

像Ole V.V.说过。您的任务实际上比链接问题讨论的递归步骤更简单。您只需要列出parent下每个目录的内容,它们可能如下所示:

Path parent = Paths.get("parent");
try (DirectoryStream<Path> childStream = Files.newDirectoryStream(parent)) {
  for (Path child : childStream) {
    try (DirectoryStream<Path> subChildStream = Files.newDirectoryStream(child)) {
      for (Path subChild : subChildStream) {
        // or just print subChild to display the full path
        System.out.println(subChild.getFildName());
      }
    }
  }
}

如果您不想处理try-with-resources块,也可以尝试Files.walkFileTree;将最大深度设置为2(因为您从parent开始),您可以覆盖preVisitDirectory()并仅打印比parent深两个的路径。

修改:已接受的答案使用旧版java.io.File API。 Java 7+代码应该更喜欢我的示例使用的java.nio.file API。

答案 2 :(得分:1)

我希望这可以解决问题:

public List<File> getThirdLayer(File root) {
        List<File> thirdLayerFiles = new ArrayList<File>();
        for (File f : root.listFiles()) {
            if (f.isDirectory()) {
                for (File f2 : f.listFiles()) {
                    if (f2.isDirectory()) {
                        thirdLayerFiles.add(f2);
                    }
                }
            }
            return thirdLayerFiles;
        }
        return null;
    }

它将返回结构的第三层列表!

答案 3 :(得分:1)

这是一个未经修饰的去。

    Path parent = FileSystems.getDefault().getPath("parent");
    Files.list(parent).forEach(child -> {
        try {
            System.out.println(Files.list(child).map(Path::getFileName).collect(Collectors.toList()));
        } catch (IOException e) {
            // TODO
        }
    });

它会打印出类似

的内容
[child1.1, child1.2]
[child2.1, child2.2]
[child3.1, child3.2]

我希望你能根据自己的需要量身定制。

答案 4 :(得分:1)

您还可以在Files-class中使用“walkFileTree”-Method。

这是一个简短的例子:

    Path startingDir = new File("parent").toPath();
    Integer depth = 2;
    EnumSet<FileVisitOption> opts = EnumSet.noneOf(FileVisitOption.class);
    FileVisitor<Path> finder = new FileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
            if (attrs.isDirectory()
                    && dir.getNameCount() - startingDir.getNameCount() == depth) {
                System.out.println(dir.toString());
            }
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
            //ignore error in subtree
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            return FileVisitResult.CONTINUE;
        }

    };
    Files.walkFileTree(startingDir, opts, depth + 1, finder);

答案 5 :(得分:1)

如果你想要它是递归的,你可以使用这样的东西:

public static void main(String[] args) {
    File file = new File(args[0]);
    List<File> results = new ArrayList<File>();
    getSubdirs(file, results, 0, 2);
    for (File f : results) {
        System.out.println(f.getAbsolutePath());
    }
}

public static List<File> getSubdirs(File file, List<File> results, int level, int targetlevel) {
    List<File> subdirs = Arrays.asList(file.listFiles(new FileFilter() {
        public boolean accept(File f) {
            return f.isDirectory();
        }
    }));
    subdirs = new ArrayList<File>(subdirs);
    if (level == targetlevel) results.addAll(subdirs);

    List<File> deepSubdirs = new ArrayList<File>();
    for(File subdir : subdirs) {
        deepSubdirs.addAll(getSubdirs(subdir, results, level + 1, targetlevel)); 
    }
    subdirs.addAll(deepSubdirs);
    return subdirs;
}

如您所见,我也改编了您所提到的原始方法。

在这种情况下,我们会创建一个空列表results,我们从级别0开始。每次调用递归方法时,我们都会向该级别添加1。我们还传递目标级别(在这种情况下为2)。我们添加了level等于targetlevel的所有结果。

请注意,这比其他人共享的非递归方法慢得多(因为你遍历每个子目录),但它更通用。

答案 6 :(得分:0)

我根据Ole V.V的评论尝试了我自己的解决方案

public static void main(String[] args) throws IOException {

    String path = "D:/PT/Projects/current/1/bwb/2.1";
    File file = new File(path);
    List<File> level1folders = getDir(file); //level 1 folders
    level1folders = new ArrayList<File>(level1folders);
    List<File> level2folders = getSubdirs(level1folders); //level 2 folders
    List<File> level3folders = getSubdirs(level2folders);    ////level 3 folders

    //print
    for (File file2 : level3folders) {
        System.out.println(file2.getName());
    }

}

private static List<File> getDir(File file) {
    List<File> subdirs = Arrays.asList(file.listFiles(new FileFilter() {
        public boolean accept(File f) {
            return f.isDirectory();
        }
    }));
    return subdirs;
}
static List<File> getSubdirs(List<File> subdirs) {
    List<File> deepSubdirs = new ArrayList<File>();
    for(File subdir : subdirs) {
        deepSubdirs.addAll(getDir(subdir)); 
    }
    //subdirs.addAll(deepSubdirs);
    return deepSubdirs;
}

但是krzydyn很好! dimo414对我来说是新的。感谢