12

我使用以下 Apache Commons 类在 Java 文件系统中列出文件:

Collection<File> allFiles = FileUtils.listFiles(rootDirectory, null, recursive);

这是一个非常漫长的过程,最多可能需要 5 分钟。

有什么方法可以在填充集合时检查集合的大小?

我尝试从一个单独的线程访问它,但只是在进程准备好之前得到了零。

4

4 回答 4

11

在您从该方法获得返回值之前,您将无法访问填充的集合,因为您无权访问此方法在内部使用的变量。

您可以通过不使用递归标志将搜索分成更小的部分,并自己处理递归以接收每个目录的集合。

如果您使用的FileVisitor是 Java 7,一个更好的选择是使用接口来探索文件系统。它有一些回调方法可以让您跟踪进度。

于 2012-09-03T10:31:05.207 回答
2

您可以使用 FileUtils IOFileFilter。

Collection<File> listFiles = FileUtils.listFiles(new File("."), counter, FileFilterUtils.trueFileFilter());

柜台将在哪里

IOFileFilter counter = new IOFileFilter() {

    @Override
    public boolean accept(File arg0, String arg1) {
        countCall();
        return true;
    }

    @Override
    public boolean accept(File arg0) {
        countCall();
        return true;
    }
};

countCall 是更新进度的方法。

于 2012-09-03T12:08:26.227 回答
1

我想您可以尝试使用执行平台特定的命令,例如将列表命令输出重定向到临时文件并使用 Java File API 读取它。

ls > temp.txt

我创建了一个简单的 shell 脚本,它将列出给定索引中的文件。

#!/bin/bash

RANGE_UP=$2
RANGE_BOT=$1

CURRENT_CNTR=0

FILENAME=._m_ls

ls -w 1 > $FILENAME
while read line
do
    if [ $CURRENT_CNTR -le $RANGE_UP -a $CURRENT_CNTR -gt $RANGE_BOT ]; then
    printf $line"\n"
    fi
    CURRENT_CNTR=`expr $CURRENT_CNTR + 1`
done < $FILENAME

您现在可以执行类似的操作./ls_range.sh 10000 30000 >temp.txt,然后使用BufferedReader不同的线程从该文件中读取。

于 2012-09-03T11:09:19.500 回答
1

您执行此操作的唯一方法(与 java7 或之前建议的拆分工作相反)是编写您自己的代码以在更新回调时搜索文件系统。

我使用了来自 的代码commons-io,并对其进行了修改以满足您的需求,显然它需要测试,但它会在找到文件时对其进行计数。

例子

interface Counter {
    void foundFile(File file);
}

final class FileSearcher {
    public static Collection<File> listFiles(File root, FileFilter filter, Counter counter) {
        Collection<File> files = new ArrayList<File>();
        File[] found = root.listFiles(filter);

        if (found != null) {
            for (int i = 0; i < found.length; i++) {
                if (found[i].isDirectory()) {
                    files.addAll(listFiles(found[i], filter, counter));
                } else {
                    files.add(found[i]);
                    counter.foundFile(found[i]);
                }
            }
        }

        return files;
    }
}

然后像这样使用它:

final AtomicInteger inte = new AtomicInteger(0);
FileSearcher.listFiles(new File("C:/"), null, new Counter() {
    @Override
    public void foundFile(File file) {
        System.out.println("found file number " + inte.addAndGet(1));
    }
});
于 2012-09-03T11:47:27.360 回答