文
章
目
录
章
目
录
了解在给定目录及其子目录中使用Java查找文件的不同方法。下面的示例将查找具有指定文件名的所有文件,如果子目录中有多个文件具有相同的名称。
1.通过遍历目录查找文件
在目录或其子目录中查找所有文件的最简单和最直接的方法是使用Files.walk()方法遍历所有文件。此方法以深度优先的方式遍历目录,因此最深的子目录中的文件将首先被搜索。
如果目录结构嵌套太多,并且我们不希望深入太多,我们可以选择传递要搜索的子目录的深度。请注意,当我们关闭流时,目录也被关闭。
String fileNameToFind = "test.txt";
File rootDirectory = new File("c:/temp");
final List<File> foundFiles = new ArrayList<>();
try (Stream<Path> walkStream = Files.walk(rootDirectory.toPath())) {
walkStream.filter(p -> p.toFile().isFile())
.forEach(f -> {
if (f.toString().endsWith(fileNameToFind)) {
foundFiles.add(f.toFile());
}
});
}
如果我们想要迭代5层子目录,那么我们可以使用以下函数:
try (Stream<Path> walkStream = Files.walk(rootDirectory.toPath(), 5)) {
...
}
如果我们想在找到第一个文件后停止搜索,那么我们可以使用路径流和Stream.findFirst()方法。
Optional<Path> foundFile;
try (Stream<Path> walkStream = Files.walk(rootDirectory.toPath())) {
foundFile = walkStream.filter(p -> p.toFile().isFile())
.filter(p -> p.toString().endsWith(fileNameToFind))
.findFirst();
}
if(foundFile.isPresent()) {
System.out.println(foundFile.get());
} else {
System.out.println("File not found");
}
2. 使用递归
递归是一种老式的方法,可以迭代所有文件和子目录,并应用自定义逻辑以匹配文件名。尽管如此,如果适合我们的解决方案,我们仍然可以使用它。
以下方法findFilesByName()递归地迭代文件和子目录,并将匹配的文件添加到foundFilesList中。
递归函数首先使用File.listFiles()方法列出所有文件,然后迭代它们。在迭代过程中,它使用file.isDirectory()方法检查所有子目录,并对它们调用listFiles()。
在递归结束后,我们可以检查在此列表中找到的文件。
final List<File> foundFilesList = new ArrayList<>();
findFilesByName(rootDirectory, fileNameToFind, foundFilesList);
public static void findFilesByName(File rootDir, String filenameToSearch, List<File> foundFilesList) {
Collection<File> files = List.of(rootDir.listFiles());
for (Iterator iterator = files.iterator(); iterator.hasNext(); ) {
File file = (File) iterator.next();
if (file.isDirectory()) {
findFilesByName(file, filenameToSearch, foundFilesList);
} else if(file.getName().equalsIgnoreCase(filenameToSearch)){
foundFilesList.add(file);
}
}
}
System.out.println(foundFilesList); //Prints the found files
3.结论
这段简短的Java教程教会我们如何在给定的目录及其子目录中按名称查找文件。我们还学习了如何控制搜索范围,限制到配置的子目录深度。如果我们想要在找到第一个匹配文件后终止搜索,我们可以使用Stream的归约方法findFirst()。