简体   繁体   English

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

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

Here is my folder structure: 这是我的文件夹结构:

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

How can I extract only the names of the third-level folders? 如何仅提取第三级文件夹的名称? (I haven't been able to find this online) (我无法在线找到它)

Output should be: 输出应为:

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

I referenced Java: how to get all subdirs recursively? 我引用了Java:如何递归获取所有子目录? to find subdirectories. 查找子目录。

To make level parametric I suggest code: 为了使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;
}

And call it: 并称之为:

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

Edit: I added verification in case of empty directory 编辑:我添加了验证,以防目录为空

Like Ole VV said. 就像Ole VV所说。 your task is actually simpler than the recursive walk the linked question discusses. 您的任务实际上比链接的问题讨论的递归遍历更简单。 You simply need to list the contents of each directory under parent , which might look something like this: 您只需要在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());
      }
    }
  }
}

You could also try Files.walkFileTree if you don't want to deal with try-with-resources blocks; 如果不想处理try-with-resources块,也可以尝试使用Files.walkFileTree setting the max-depth to 2 (since you're starting from parent ) you can override preVisitDirectory() and only print paths two-deeper than parent . 将最大深度设置为2(因为您是从parent开始的),您可以覆盖preVisitDirectory()并且仅打印比parent深2的路径。

Edit: The accepted answer uses the legacy java.io.File API. 编辑:接受的答案使用旧版java.io.File API。 Java 7+ code should prefer the java.nio.file APIs, which my example uses. Java 7+代码应首选我的示例使用的java.nio.file API。

I hope this will do the trick: 我希望这可以解决问题:

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

It will return a List of the thirdLayer of your structur! 它将返回您结构的第三层的列表!

Here's an unpolished go. 这是未抛光的。

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

It would print someting like 它会打印出类似

[child1.1, child1.2]
[child2.1, child2.2]
[child3.1, child3.2]

I hope you can tailor it to your needs. 希望您可以根据自己的需要进行调整。

You can also use the "walkFileTree"-Method in the Files-class. 您也可以在Files类中使用“ walkFileTree”方法。

Here a short example: 这是一个简短的例子:

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

If you want it to be recursive, you could use something like this: 如果您希望它是递归的,则可以使用如下代码:

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

As you can see, I adapted the original method you referred too. 如您所见,我也修改了您引用的原始方法。

In this case, we create an empty list results and we start with level 0 . 在这种情况下,我们创建一个空列表results并从级别0开始。 Each time the recursive method is called, we add 1 to the level. 每次调用递归方法时,我们在级别上加1 We also pass a target level (in this case 2 ). 我们还通过了目标水平(在这种情况下为2 )。 We add all the results for which the level equals the targetlevel . 我们将level等于targetlevel level所有结果targetlevel

Note that this is much slower than the non-recursive methods shared by the other people (because you loop over every subdirectory), but it is more generic. 请注意,这比其他人共享的非递归方法要慢得多(因为您遍历每个子目录),但是它更通用。

I have tried my own solution based on comment by Ole VV 我已经根据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;
}

But krzydyn is good one! 但是krzydyn是个好人! dimo414 is new to me. dimo414对我来说是新的。 Thanks 谢谢

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

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