【问题标题】:Java: How to get only subdirectories name present at certain level?Java:如何仅获取特定级别的子目录名称?
【发布时间】:2016-12-27 11:21:36
【问题描述】:

这是我的文件夹结构:

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? 来查找子目录。

【问题讨论】:

  • 你链接的代码有点老了,今天你可以使用PathFiles以及java.nio.files中的相关类。无论如何,不​​用深思熟虑,不就是把递归从其他代码中取出来吗?
  • 仅供参考,我重新格式化了您的问题以使目录结构更清晰。如果我误解了您所描述的内容,我们深表歉意。

标签: java directory-structure


【解决方案1】:

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

编辑:我添加了空目录的验证

【讨论】:

    【解决方案2】:

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

    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 的所有结果。

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

    【讨论】:

      【解决方案3】:

      这是一个未完善的过程。

          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】:

        我希望这能解决问题:

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

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

        【讨论】:

        • 请注意:您应该从问题(父母、孩子)中提取术语。另外我认为您的嵌套 for 块不是您的想法。
        • 作为 Ole V.V.说它没有必要递归。另外我只是认为在这种情况下 root 与 parent 完全相同。不过谢谢你的留言;D
        【解决方案5】:

        您也可以在文件类中使用“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);
        

        【讨论】:

          【解决方案6】:

          像 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。

          【讨论】:

          • 只是为了弄清楚这一点:您介意添加导入语句吗?以便清楚您正在使用哪些类。您使用哪个 Java 版本?
          • @Matthias 这是使用 Ole V.V. 的 java.nio.files API。在他们的评论中提到。它是在 Java 7 中引入的。我强烈反对在新代码中使用 java.io.File,因为它有许多 java.nio.files 解决的缺点。
          【解决方案7】:

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

          【讨论】:

            猜你喜欢
            • 2012-01-02
            • 2014-12-29
            • 1970-01-01
            • 1970-01-01
            • 2010-09-06
            • 1970-01-01
            • 2011-12-08
            • 2015-01-21
            • 2015-03-05
            相关资源
            最近更新 更多