繁体   English   中英

Java:如何仅获取在特定级别存在的子目录名称?

[英]Java: How to get only subdirectories name present at certain level?

这是我的文件夹结构:

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:如何递归获取所有子目录? 查找子目录。

为了使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);

编辑:我添加了验证,以防目录为空

就像Ole VV所说。 您的任务实际上比链接的问题讨论的递归遍历更简单。 您只需要在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深2的路径。

编辑:接受的答案使用旧版java.io.File API。 Java 7+代码应首选我的示例使用的java.nio.file API。

我希望这可以解决问题:

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

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

这是未抛光的。

    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]

希望您可以根据自己的需要进行调整。

您也可以在Files类中使用“ walkFileTree”方法。

这是一个简短的例子:

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

如果您希望它是递归的,则可以使用如下代码:

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 level所有结果targetlevel

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

我已经根据Ole VV的评论尝试了自己的解决方案

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对我来说是新的。 谢谢

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM