[英]How to efficiently test if files with a matching filename (regex or wildcard) exists in a directory?
我正在寻找一种有效的方法来测试是否存在具有特定模式文件名的文件。
使用通配符的示例:
使用正则表达式的示例:
问题是我必须测试的目录最多包含500.000个文件。 我知道执行此类测试的唯一方法是使用File类的方法:
String[] list()
String[] list(FilenameFilter filter)
File[] listFiles()
File[] listFiles(FileFilter filter)
File[] listFiles(FilenameFilter filter)
问题在于,基本上它们都是以相同的方式实现的:首先,调用list()以获取所有可用文件,然后它们在其上应用过滤器。
请想象一下,如果我们想将此应用到包含500.000个文件的文件夹中,将会发生什么...
Java中是否有其他方法可以检索与目录中的文件有关的第一个匹配文件的文件名,而不必枚举所有文件?
如果JNI是唯一的选择-是否有一个库可以做到这一点,它带有针对六个主要平台(分别为32位和64位的Linux,Windows和OSX)的预编译二进制文件?
我觉得你很困惑。 据我所知,当前没有操作系统在其文件系统界面中支持模式列表/搜索。 所有支持模式的实用程序都通过列出目录(例如,在POSIX系统上使用readdir()
来执行此操作,然后执行字符串匹配。
因此,没有通用的底层方法可以用Java或任何其他语言更有效地执行此操作。 也就是说,您应该至少研究以下方法:
请确保仅检索文件名,并且不对文件节点本身进行探测以获取其他元数据(例如其大小),因为这将导致每个文件的附加操作。
检索一次文件列表并缓存它,可能与文件系统事件通知接口(例如JNotify或Java 7 WatchService接口 )进行更新关联。
编辑:
我看了看我的Java实现。 File
类方法中唯一明显的缺点是,一旦找到匹配项,列出目录就不会停止。 但是,这仅是重要的,如果您只执行一次搜索-否则缓存整个目录列表仍然会更加有效。
如果你可以使用一个相对较新的Java版本,你可能想看看在Java NIO类( 1 , 2 ),这似乎并不具有相同的弱点。
这在我的机器上花了大约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.));
}
}
我认为您正在把众所周知的购物车摆在马匹前面。
正如Knuth所说,过早的优化是万恶之源。 您是否尝试过使用FileFilter方法并发现它对于应用程序来说太慢了?
为什么一个文件夹中有这么多文件? 也许更有益的方法是以某种方式拆分这些文件,而不是将它们全部放在一个文件夹中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.