章
目
录
学习使用各种Java API,如Files.list()和DirectoryStream,以递归方式列出目录中存在的所有文件(包括隐藏文件)。
使用外部迭代(for循环),请使用DirectoryStream。
要使用Stream API操作,请使用Files.list()。
1.在给定目录中仅列出文件
1.1 使用Files.list()的File流
如果我们只对非递归地列出文件感兴趣,并且要排除所有子目录及其子目录中的所有文件,那么可以使用此方法。
- 使用Files.list()读取所有文件和目录条目。
- 使用Predicate File::isFile检查给定条目是否为文件。
- 将所有筛选后的条目收集到列表中。
//源目录
String directory = "C:/temp";
// 只读取目录里的文件
try {
List<File> files = Files.list(Paths.get(directory))
.map(Path::toFile)
.filter(File::isFile)
.collect(Collectors.toList());
files.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
1.2. 使用DirectoryStream循环遍历文件
DirectoryStream是Java 7的一部分,用于在for-each循环样式中迭代目录中的条目。
关闭目录流会释放与流关联的任何资源。未关闭流可能导致资源泄漏。try-with-resources语句提供了一个有用的结构,以确保流被关闭。
List<File> fileList = new ArrayList<>();
try (DirectoryStream<Path> stream = Files
.newDirectoryStream(Paths.get(directory))) {
for (Path path : stream) {
if (!Files.isDirectory(path)) {
fileList.add(path.toFile());
}
}
}
fileList.forEach(System.out::println);
2. 在给定目录及其子目录中列出所有文件
2.1 用于路径流的Files.walk()方法
walk()方法返回一个从给定起始文件/目录开始的深度优先遍历文件树的Stream。
注意,此方法访问文件树的所有级别。
String directory = "C:/temp";
List<Path> pathList = new ArrayList<>();
try (Stream<Path> stream = Files.walk(Paths.get(directory))) {
pathList = stream.map(Path::normalize)
.filter(Files::isRegularFile)
.collect(Collectors.toList());
}
pathList.forEach(System.out::println);
如果还想把目录的路径也列出来的话,那就把Files::isRegularFile这个过滤条件去掉。
2.2 简单递归
我们也可以使用递归来编写文件树遍历逻辑。如果在添加条目到文件列表之前想要执行一些中间步骤/检查,那么这会给我们一点更多的灵活性。请注意,如果正在处理一个大的目录,那么使用DirectoryStream表现会更好。
我们也可以用递归来实现文件树遍历的逻辑,这种方式可以让我们在添加文件到列表之前执行一些额外的步骤或检查。
String directory = "C:/temp";
//递归列出所有文件
List<File> fileList = listFiles(directory);
fileList.forEach(System.out::println);
private static List<File> listFiles(final String directory) {
if (directory == null) {
return Collections.EMPTY_LIST;
}
List<File> fileList = new ArrayList<>();
File[] files = new File(directory).listFiles();
for (File element : files) {
if (element.isDirectory()) {
fileList.addAll(listFiles(element.getPath()));
} else {
fileList.add(element);
}
}
return fileList;
}
不过要注意,如果目录很大,使用DirectoryStream会表现得更好。
3.列出所有特定扩展名的文件
要获取仅特定扩展名的所有文件的列表,请将两个predicate: Files::isRegularFile
和filename.endsWith(".extension")
一起使用。
在这个例子中,我们列出了给定目录及其所有子目录中的所有.java文件。
要获取所有特定扩展名的文件列表,可以将Files::isRegularFile和filename.endsWith(“.extension”)这两个条件结合起来使用。比如在这个例子中,我们列出了给定目录及其所有子目录中的所有.java文件。
String directory = "C:/temp";
//递归列出所有文件
List<Path> pathList = new ArrayList<>();
try (Stream<Path> stream = Files.walk(Paths.get(directory))) {
// 流中处理一些事情
pathList = stream.map(Path::normalize)
.filter(Files::isRegularFile)
.filter(path -> path.getFileName().toString().endsWith(".java"))
.collect(Collectors.toList());
}
pathList.forEach(System.out::println);
}
4. 列出所有隐藏文件
在上面的任何一个例子中,我们都可以使用过滤表达式file -> file.isHidden()来找到所有的隐藏文件。
在上面的例子中,我们了解到如何使用Java 8 API来递归遍历目录中的文件,并使用不同的搜索方法来循环遍历文件。您可以随意修改代码并尝试使用它。