【问题标题】:Recursively finding only directories with FileUtils.listFiles使用 FileUtils.listFiles 递归查找目录
【发布时间】:2009-05-23 01:50:12
【问题描述】:

我想收集一个目录下的所有文件列表,特别是包括子目录。我不喜欢自己做事,所以我使用来自 Apache Commons IO 的FileUtils.listFiles。所以我有类似的东西:

import java.io.File;
import java.util.Collection;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;

public class TestListFiles {
  public static void main(String[] args) {
    Collection<File> found = FileUtils.listFiles(new File("foo"),
        TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
    for (File f : found) {
      System.out.println("Found file: " + f);
    }
  }
}

问题是,这似乎只能找到普通文件,而不是目录:

$ mkdir -p foo/bar/baz; touch foo/one_file
$ java -classpath commons-io-1.4.jar:. TestListFiles
Found file: foo/one_file

我已经将TrueFileFilter 传递给这两个过滤器,所以我想不出任何更具包容性的东西。我希望它列出:"foo", "foo/one_file", "foo/bar", "foo/bar/baz"(以任何顺序)。

我也会接受非FileUtils 解决方案,但是必须编写自己的 BFS,甚至从我得到的列表中收集父目录集似乎很愚蠢。 (这无论如何都会错过空的子目录。)这是在 Linux 上,FWIW。

【问题讨论】:

    标签: java apache-commons-io


    【解决方案1】:

    你试过简单吗:

    File rootFolder = new File(...);
    File[] folders = rootFolder.listFiles((FileFilter) FileFilterUtils.directoryFileFilter());
    

    这似乎对我有用。 当然,您将需要递归。

    希望对你有帮助。

    【讨论】:

    • 谢谢,这个最适合我。我不想为 VFS 添加另一个库。
    • 问题是 Java io 非常慢。
    【解决方案2】:

    一个旧答案,但这对我有用:

    FileUtils.listFilesAndDirs(new File(dir), TrueFileFilter.INSTANCE, DirectoryFileFilter.DIRECTORY);
    

    同时显示:

    我用:

    FileUtils.listFilesAndDirs(new File(dir), new NotFileFilter(TrueFileFilter.INSTANCE), DirectoryFileFilter.DIRECTORY)
    

    只显示目录,不显示文件...

    【讨论】:

    • 这对我来说比 user573041 对我杀死我的应用程序的回答要慢得多。
    • “new NotFileFilter(TrueFileFilter.INSTANCE)”的替代品只是“FalseFileFilter.INSTANCE”。我认为您使用“FileUtils.listFilesAndDirs(...)”的答案最适合,是 OP 要求的简单解决方案。
    • 我使用 Collection c = FileUtils.listFilesAndDirs(new File("target"), FalseFileFilter.INSTANCE,TrueFileFilter.INSTANCE);
    【解决方案3】:

    我在大多数重要的应用程序中都避免使用 Java IO 库,而是更喜欢 Commons VFS。我相信使用适当的参数调用this method 将实现您的目标,但我认为它在实现功能方面还有很长的路要走。

    具体来说,这段代码会做你想做的事:

        FileObject[] files = fileObject.findFiles(new FileSelector() {
            public boolean includeFile(FileSelectInfo fileInfo)  {
                return fileInfo.getFile().getType() == FileType.FOLDER; }
    
            public boolean traverseDescendents(FileSelectInfo fileInfo) {
                return true;
            }
        });
    

    其中 fileObject 是 FileObject 的一个实例。

    【讨论】:

    • “此方法”是一个断开的链接。
    【解决方案4】:

    如果您查看source code 并在JavaDoc 中的两行之间阅读,您会发现——不幸的是——这个API 并不是为满足您的需要而设计的。它将返回与提供的参数匹配的文件列表(不是文件和目录的列表)。在源代码中——查看方法innerListFiles——你会看到目录被搜索并且没有被添加到结果列表中。

    我不知道有任何公共 API 可以满足您的需求。希望其他人会知道一个。大多数可能是 DFS,而不是 BFS,这可能对您的目的很重要,也可能无关紧要。 (到目前为止,我看过的所有 Java 代码都通过深度优先搜索完成了目录树遍历。当然,这并不意味着 BFS 不存在.)

    如果您真的想要一个给定目录下的所有内容列表,您可以轻松创建自己的列表。但我理解你不想重新发明轮子的愿望。

    注意:Apache Commons Finder 可能会支持你需要的东西,但是这个库在 Commons Sandbox 中,这意味着它在这个阶段更具实验性。它可能是完整的,也可能不是完整的,它可能会或可能不会被维护。对于您正在寻找的东西,它也可能是重量级的。

    【讨论】:

    • 感谢您的指点——我最终可能只是复制它并使其工作。我想这就是我假设 Linux 上的所有文件(目录、链接、管道、设备)都是 Commons 定义的文件。
    • 我会做出和你一样的假设——直到它不起作用。他们真的应该让他们的 JavaDoc 更加明确以使其清晰。
    • 哇,感谢您的指点。 javadoc 中没有提及排除目录。我不知道到底谁认为目录不是文件!
    【解决方案5】:

    更简单+完整的Commons VFS 解决方案:

    FileSystemManager fsManager = VFS.getManager();
    FileObject fileObject = fsManager.resolveFile( "yourFileNameHere" );
    FileObject[] files = fileObject.findFiles( new FileTypeSelector( FileType.FOLDER ) )
    

    【讨论】:

      【解决方案6】:

      根据他们的 API,它应该可以工作。

      这是我自己的FileUtils 版本,不如Commons IO 完整,它只包含我需要的内容。搜索 findFiles 或者你可以使用 iterate 来避免创建巨大的列表(有时/大部分时间你只是想对这些文件做一些事情,所以将它们收集在一个列表中没有意义)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多