如何有效地测试目录中是否存在具有匹配文件名(正则表达式或通配符)的文件?

时间:2011-11-01 18:44:48

标签: java regex file find wildcard

我正在寻找一种有效的方法来测试是否存在具有特定模式的文件名的文件。

使用通配符的示例:

  • ????。*
  • ???????。*
  • *。PNG
  • *。JPG

使用正则表达式的示例:

  • [012] {4}。*
  • [012] {7}。*

问题是我必须测试的目录包含多达500.000个文件。 我知道执行此类测试的唯一方法是使用File类的方法:

String[] list()
String[] list(FilenameFilter filter)
File[] listFiles()
File[] listFiles(FileFilter filter)
File[] listFiles(FilenameFilter filter)

问题在于,基本上它们都以相同的方式实现:首先是调用列表()以获取所有可用文件,并且它们在其上应用过滤器。

如果我们想在包含 500.000 文件的文件夹中应用此功能,请想象一下会发生什么......

如果在Java中有任何替代方法可以检索关于目录中文件的第一个匹配文件的文件名而不必枚举所有这些文件?

如果JNI是唯一的选择 - 是否有一个库可以为六个主要平台(Linux,Windows和OSX,每个32位和64位)预先编译的二进制文件做到这一点?

3 个答案:

答案 0 :(得分:3)

我觉得你很困惑。据我所知,当前的操作系统在其文件系统界面中不支持模式列表/搜索。所有支持模式的实用程序都通过列出目录(例如在POSIX系统上使用readdir())然后执行字符串匹配来实现。

因此,没有通用的低级方法可以在Java或任何其他语言中更有效地执行此操作。也就是说,您应该至少调查以下方法:

  • 确保您只检索文件名,并且不会探测文件节点本身以获取其他元数据(例如它们的大小),因为这会导致每个文件的附加操作。

  • 检索文件列表一次并缓存它,可能与更新的文件系统事件通知界面相关联(例如JNotifyJava 7 WatchService interface)。< / p>

编辑:

我看了一下我的Java实现。 File类的方法唯一明显的缺点是,一旦找到匹配项,列表目录就不会停止。但是,如果您只执行一次搜索,那只会很重要 - 否则缓存完整目录列表的效率会更高。

如果您可以使用相对较新的Java版本,您可能需要查看似乎没有相同的Java NIO类(12)弱点。

答案 1 :(得分:1)

这在我的机器上花了大约1分钟(这是旧的)

import java.io.*;
import java.util.*;
import java.util.regex.*;
public class Main {
    static void match(File dir, Pattern pattern, List<File> matching) {
        File[] files = dir.listFiles();
        if(files==null) {
            System.out.println(dir + " is strange!");
            return;
        }
        for (File file : files)
            if (file.isDirectory()) match(file, pattern, matching);
            else if (file.isFile()) {
                Matcher matcher = pattern.matcher(file.getName());
                if (matcher.matches()) {
                    matching.add(file);
                    //System.out.println(file + "************");
                }
            }
    }
    static void makeFiles(File dir,int n) throws IOException {
        for(int i=0;i<n;i++) {
            File file=new File(dir,i+".foo");
            FileWriter fw=new FileWriter(file);
            fw.write(1);
            fw.close();
        }
    }
    public static void main(String[] args) throws IOException {
        File dir = new File("data");
        final int n=500000;
        //makeFiles(dir,n);
        long t0=System.currentTimeMillis();
        Pattern pattern = Pattern.compile(".*\\.foo");
        List<File> matching = new LinkedList<File>();
        match(dir, pattern, matching);
        long t1=System.currentTimeMillis();
        System.out.println("found: "+matching.size());
        System.out.println("elapsed time: "+(t1-t0)/1000.);
        System.out.println("files/second: "+n/((t1-t0)/1000.));
    }
}

答案 2 :(得分:0)

我认为你把这个众所周知的推车放在马前。

  1. 正如Knuth所说,过早优化是万恶之源。您是否尝试过使用FileFilter方法并发现它对于应用程序来说太慢了?

  2. 为什么一个文件夹中有这么多文件?也许更有利的方法是以某种方式拆分这些文件,而不是将它们全部放在一个文件夹中。