Java:列出单个目录中的所有文件(10-20,000 +)

时间:2010-12-10 16:19:48

标签: java

我想快速有效地列出单个目录中包含的大量文件(10,2万个左右)。 我已经阅读了很多帖子,特别是在这里解释了Java实现这一目标的短暂内容,主要是由于底层文件系统(可能Java 7有一些答案)。 这里的一些帖子提出了替代方案,如本机调用或管道等,我确实理解在正常情况下最好的选项是java调用 - String [] sList = file.list();这比file.listFiles()略胜一筹; 此外,还建议使用多线程(也是Executor服务)。

嗯,这里的问题是我对如何编写多线程方式的实用技巧很少。所以我的逻辑肯定是不正确的。不过,我试过这种方式:

  1. 创建了几个线程对象的列表
  2. 执行此列表的循环,称为.start()并立即.sleep(500)
  3. 在线程类中,过度运行运行方法以包含.list()
  4. 像这样的东西,来电者班 -

    String[] strList = null;  
    for (int i = 0; i < 5; i++){  
       ThreadLister tL = new ThreadLister(fit);  
       threadList.add(tL);  
    }  
    for (int j = 0; j < threadList.size(); j++) {  
       thread = threadList.get(j);  
       thread.start();  
       thread.sleep(500);  
    }  
    strList = thread.fileList;  
    

    和Thread类为 -

    public String[] fileList;  
    public ThreadLister(File f) {  
       this.f = f;  
    }  
    public void run() {  
       fileList = f.list();  
    }  
    

    我猜这可能与多线程有关。 我非常感谢我对多线程要求的解决方案。额外的好处是我会学到更多关于实际多线程的知识。

      

    查询更新

    嗯,显然多线程不会对我有所帮助(我现在意识到它实际上并不是解决方案)。谢谢你帮我排除线程 所以我试过了,
    1.来自apache commons的FileUtils.listFiles() - 没有多大区别 2.本地电话即。 exec("cmd /c dir /B .\\Test") - 这里执行速度很快,但是当我使用需要很长时间的while循环读取Stream时。

    实际上我需要的是文件名,取决于单个目录中大约100k文件中的某个过滤器。所以我使用的是File.list(new FileNameFilter()) 我相信FileNameFilter没有任何好处,因为它会首先尝试匹配所有文件,然后给出输出。
    是的,我理解,我需要一种不同的方法来存储这些文件。我可以尝试的一个选项是将这些文件存储在多个目录中,我还没试过这个(我不知道这是否足够了) - 正如Boris之前的建议
    还有什么可以是更好的选择,对于具有文件名匹配的Unix ls的本机调用是否有效。我知道在Windows上它不起作用,我的意思是除非我们在同一目录中搜索

    亲切的问候

4 个答案:

答案 0 :(得分:6)

多线程对列出多个目录很有用。但是,您不能将单个调用拆分为单个目录,我怀疑如果操作系统以任何顺序返回文件,它会更快。

学习多线程的第一件事是,并非所有解决方案都只是通过使用多个线程来更快或更简单。

答案 1 :(得分:2)

这是一个完全不同的建议。你尝试过使用Apache Commons File util吗?

http://commons.apache.org/io/api-release/index.html查看方法FileUtils.listFiles()。

它将列出目录中的所有文件。也许它足够快并且足够优化以满足您的需求。也许你真的不需要重新发明轮子,解决方案已经在那里了?

答案 2 :(得分:0)

最终,我所做的是。
1.作为一个quickfix,为了解决这个问题,我使用本机调用将所有文件名写入临时文本文件,然后使用BufferedReader读取每一行。
2.编写实用程序以将非活动文件(大多数)存档到其他存档位置,从而减少活动目录中的总文件数。这样普通的list()调用返回得更快 3.作为一个长期的解决方案,我将修改所有这些文件的存储方式并创建一种目录层次结构,其中每个目录将保存相对较少的文件,因此list()可以非常快速地工作。

我想到了一件事情,我注意到测试时是这个列表(),当第一次运行需要很长时间但后续请求非常快。让我相信JVM无意中检索到堆上的列表。我尝试了一些事情,比如向dir添加文件或更改File变量名称,但响应仍然是即时的。所以我相信这个数组位于堆上直到gc'ed并且Java智能地响应相同的请求。 <*Am I right? or is that not how it behaves? some explanation pls.*>
因此,我想,如果我可以编写一个小程序来每天获取此列表并保留一个静态引用,那么这个数组将不会被gc'ed并且每个检索此列表的请求都会很快。 <*Again, some comments/suggestion appreciated.*>
有没有办法配置Tomcat,其中GC可能gc所有其他未引用的对象,但不适用于指定的那些?有人告诉我在Linux中这样的东西显然是针对操作系统级别实现的,我不知道它的真实与否。

答案 3 :(得分:0)

您使用的是哪个文件系统?每个文件系统对目录可以拥有的文件/文件夹数量(包括目录深度)有自己的限制。所以不确定如何创建,如果通过某个程序创建,你可以读回所有文件。

如上所述,FileNameFilter是一个帖子文件名过滤器,因此我不确定它是否会有任何帮助(尽管您可能正在创建较小的文件列表列表)作为每个listFiles()方法会得到完整的清单。

例如: 1)假设线程1正在捕获以“T * ”开头的文件名列表,listFiles()调用将检索所有数千个文件名,然后根据FileNameFilter条件进行过滤 2)如果捕获以“S *”开头的文件名列表,则线程2将重复从1开始的所有步骤。

因此,您多次读取目录列表会对Heap / JVM本机调用/文件系统等施加越来越多的负载。

如果可能,最好的建议是重新组织目录结构。