我有一个存储100万个文件的位置。我想获取列表中的所有文件,并从该列表中找到文件名中包含单词的所有文件。这里唯一重要的是性能应该非常好。所有事情都应该很快发生,因此我正在寻找最快的方法。我很困惑应该使用Java传统文件对象还是应该使用NIO。我尝试了文件对象,如下所示:
String[] fileList = null;
String fileNamePart = "somepartoffileName";
try{
File rootFolder = new File(dir);
if(rootFolder.isDirectory()){
fileList = rootFolder.list();
}
catch(Exception e){
System.out.println("Not a valid directory "+dir);
}
String[] listFiles = Arrays.stream(fileList).filter(s ->
s.contains(FileNamePart)).toArray(String []::new);
有没有更快的方法来实现这一目标?我不介意使用文件数组或nio的东西,但我的性能应该更快。另外,要匹配的模式可以是1到1000。因此,可以有一个字符串要匹配,或者该字符串可以包含1000个逗号分隔的值
答案 0 :(得分:1)
最好不要创建所有文件的列表。传统上可以使用FileNameFilter,但可以使用新的流:
Path path = Paths.get(dir);
String[] listFiles = Files.list(path)
.map(p -> p.getFileName().toString())
.filter(s -> s.contains(FileNamePart)).toArray(String []::new);
列表似乎更通用:
List<String> listFiles = Files.list(path)
.map(p -> p.getFileName().toString())
.filter(s -> s.contains(FileNamePart))
.collect(Collectors.toList());
感谢@jaspreet提到了不需要的子目录(我用.walk
而不是.list
)。
答案 1 :(得分:0)
您应该利用FileVisitor
中的NIO2。 Oracle在各种情况下都详细介绍了example遍历文件树的情况:
import static java.nio.file.FileVisitResult.*;
// The file we are looking for.
Path lookingFor = ...;
public FileVisitResult
visitFile(Path file,
BasicFileAttributes attr) {
if (file.getFileName().equals(lookingFor)) {
System.out.println("Located file: " + file);
return TERMINATE;
}
return CONTINUE;
}
您不需要为此将整个列表存储在内存中。
答案 2 :(得分:0)
即使使用Java 8之前的标准,您的代码也不必要地复杂。 API specification没有提到为无效目录引发的任何异常(该方法将返回null
),因此没有理由添加此异常处理。此外,如果文件不是目录,该方法将返回null
,因此rootFolder.isDirectory()
测试也已过时。
因此,获取未过滤的列表就像
File rootFolder = new File(dir);
String[] fileList = rootFolder.list();
,并且很容易使用Java 8功能添加过滤器,现在调用File.list(FilenameFilter)
:
File rootFolder = new File(dir);
String[] fileList = rootFolder.list((p, n) -> n.contains(fileNamePart));