【问题标题】:Get all folders with a given name获取具有给定名称的所有文件夹
【发布时间】:2013-04-19 09:54:54
【问题描述】:

我正在寻找在给定目录中查找所有同名文件夹的解决方案。

所以我的文件夹结构是这样的:

                                       Root
                         |                |             |
                     android          windows          ios
                    |       |        |       |       |      | 
                  focus    normal  focus   normal  focus   normal

注意:客户端和图标集之间有更多文件夹,这就是我需要递归的原因。

我想获得一个包含所有路径的 ArrayList,例如普通文件夹。 虽然递归总是让我很困惑,但我无法做到。

这是我的第一次尝试,它应该返回根文件夹中包含的 ALL 目录(参数路径)。字符串图标集应在之后定义搜索文件夹的名称。

private static ArrayList<String> getAllIconSetFolders(String path, String iconset) {
        ArrayList<String> pathes = new ArrayList<String>();

        File folder = new File(path);
        File[] listOfFiles = folder.listFiles();

        for (File file : listOfFiles) {
            if (file != null && file.isDirectory()) {
                pathes.addAll(getAllIconSetFolders(file.getAbsolutePath(), iconset));
            }
        }
        return pathes;
    }

在这种情况下,它将返回一个空的 ArrayList。

如何获取(String iconset = "normal" 时的普通文件夹)的所有路径,以便我的结果如下所示:

  • “根/android/[...]/正常”
  • “根/windows/[...]/正常”
  • “根/ios/[...]/正常”

【问题讨论】:

  • file 不能是 null。删除该检查。递归地从根文件夹中获取所有文件并不难,你应该可以用谷歌搜索它。
  • 我在一些 JVM 上读到它可能会发生,这就是它存在的原因
  • 你还有参考吗?我很想看看。
  • 你有权限读取文件夹和文件吗?
  • 我去看看。是的,我想我可以这样做来接收所有子文件夹,但是我怎样才能将具有给定名称的文件夹添加到我的列表中?是的,我拥有所有权限

标签: java recursion directory


【解决方案1】:

经过测试。作品。需要 Java 7。

public static void main(String[] args) {
    List<String> paths = new ArrayList<String>();
    getAllFolders("/path/to/folder", "normal", paths);
}


private static void getAllFolders(String path, String folderName, List<String> paths) throws Exception {

    Path mainPath = Paths.get(path);
    Iterator<Path> stream = Files.newDirectoryStream(mainPath).iterator();

    while(stream.hasNext()) {
        Path currentPath = stream.next();
        String currentFolderName = currentPath.getFileName().toString();
        if(currentFolderName.equals(folderName)) {
            paths.add(currentPath.toString());
        }
        getAllFolders(currentPath.toString(), folderName, paths);
    }

}

【讨论】:

    【解决方案2】:

    在目录中搜索目录时,一种优雅的方法是使用FileFilter 或使用FileNameFilter 进行名称匹配。最重要的是,您应用标准递归方式,完整的解决方案将是:

    static void test()
    {
        File f = new File("e:\\folder");
        List<File> res = new ArrayList<File>();
        search(f, res, "normal");
        System.out.println(res);
        search(f, res, "focus");
        System.out.println(res);
    }
    
    static void search(File f, List<File> res, final String search)
    {
        if(f.isDirectory())
        {
            File[] result = f.listFiles(new FilenameFilter()
            {
                public boolean accept(File file, String name)
                {
                    return file.isDirectory() && name.equals(search);
                }
            });
            if(result != null)
            {
                for(File file : result)
                {
                    res.add(file);
                }
            }
    
            //search further recursively
            File[] allFiles = f.listFiles();
            if(allFiles != null)
            {
                for(File file: allFiles)
                {
                    search(file, res, search);
                }
            }
        }
    }
    

    或者你可以extend FileNameFilterNormalDirFilterFocusDirFilter 在那里你可以硬编码特定的文件夹搜索名称。在递归期间列出文件时使用这些特定过滤器的实例。

    【讨论】:

    • 虽然一开始这看起来很优雅,但递归到所有文件夹(无论名称如何)的需要使得过滤器在这种情况下的用处不大。
    • @DuncanJones 包含一个完整的解决方案,过滤器是查找文件搜索要求的内置方式,应该是 IMO 的首选。
    • 我不同意。比较 my answer 和你的 - 在这种情况下,我的更易于维护。但是,在很多情况下过滤器是合适的。
    • +1,但我认为这对我的需求来说太复杂了。我喜欢邓肯的回答,因为它就是这么简单:)
    【解决方案3】:

    我刚刚测试了以下代码,它似乎可以正常工作:

    public static List<File> findDirectoriesWithSameName(String name, File root) {
      List<File> result = new ArrayList<>();
    
      for (File file : root.listFiles()) {
        if (file.isDirectory()) {
          if (file.getName().equals(name)) {
            result.add(file);
          }
    
          result.addAll(findDirectoriesWithSameName(name, file));
        }
      }
    
      return result;
    }
    

    您的原始代码几乎就在那里,您只是省略了实际将匹配目录添加到结果列表的部分。


    测试:

    C:\tmp\foo
    C:\tmp\foo\bar
    C:\tmp\foo\baz
    C:\tmp\foo\baz\foo
    C:\tmp\foo\baz\foo\bar
    

    使用

    public static void main(String[] args) throws Exception {
      List<File> files = findDirectoriesWithSameName("foo", new File("C:\\tmp"));
    
      for (File f :files) {
        System.out.println(f);
      }    
    }
    

    输出:

    C:\tmp\foo
    C:\tmp\foo\baz\foo
    

    【讨论】:

    • 非常感谢,正是我想要的 :)
    【解决方案4】:

    您需要将目录名称添加到pathes,否则它将始终为空。你的代码应该是这样的:

    private static List<String> getAllIconSetFolders(String path, String iconset) 
    {
      List<String> pathes = new ArrayList<String>();
    
      File folder = new File(path);
    
      for (File file : folder.listFiles()) 
      {
        if (file.isDirectory()) 
        {
          if (file.getName().equals(iconset))
          {
            pathes.add(file.getAbsolutePath());
          }
          else
          {
            pathes.addAll(getAllIconSetFolders(file.getAbsolutePath(), iconset));
          }
        }
      }
    
      return pathes;
    }
    

    这假定iconset 是您要查找的目录的名称,并且具有该名称的目录可以在目录树中多次存在。

    【讨论】:

      【解决方案5】:

      如果你有这个结构,你能不做吗

      public static List<File> subdirectories(File root, String toFind) {
          List<File> ret = new ArrayList<File>();
          for(File dir : root.listFiles()) {
              File dir2 = new File(dir, toFind);
              if (dir2.isDirectory())
                  ret.add(dir2);
          }
          return ret;
      }
      

      【讨论】:

      • 嗯,中间还有更多的文件夹,我没有提到,这就是我想我需要递归的原因:/
      猜你喜欢
      • 1970-01-01
      • 2014-07-30
      • 1970-01-01
      • 1970-01-01
      • 2015-03-19
      • 1970-01-01
      • 2013-04-29
      • 2019-05-29
      • 1970-01-01
      相关资源
      最近更新 更多