> 文章列表 > 【java】 DirectoryStream 及其简单使用

【java】 DirectoryStream 及其简单使用

【java】 DirectoryStream 及其简单使用

DirectoryStream是Java NIO.2中用于遍历目录的一个接口类,它可以用来获取指定目录下的所有文件和子目录。在本篇文章中,将通过介绍DirectoryStream的一些常用方法和使用情景,并给出3个示例代码,帮助读者更深入地了解文件和目录操作。

DirectoryStream 常用方法

在 Java 中,要构建一个 DirectoryStream 实例,需要使用 Files 类中的 newDirectoryStream() 方法。这个方法使用一个 Path 对象作为参数,指定要遍历的目录路径。

以下是创建一个 DirectoryStream 实例的基本语法:

Path directoryPath = Paths.get("your-directory-path");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath)) {// 迭代处理目录中的文件和子文件夹
}

在上述代码中,我们首先使用 Paths.get() 方法构造一个 Path 类型的对象,以表示要遍历的目录路径。然后,我们使用 Files.newDirectoryStream() 方法创建一个 DirectoryStream 实例,并且在 try-with-resources 语句块中使用它来处理目录中的文件和子文件夹。

DirectoryStream 接口定义了一个迭代器方法 iterator(),这个方法可以用来遍历目录中的文件和子文件夹。调用 DirectoryStream 的 iterator() 方法会返回一个 DirectoryIterator 对象。我们可以使用 DirectoryIterator 的 hasNext() 和 next() 方法来检查目录是否还有未遍历的元素,并依次访问这些元素。

以下是使用 DirectoryStream 进行遍历的例子:

Path directoryPath = Paths.get("your-directory-path");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath)) {for (Path file : stream) {System.out.println(file.getFileName());}
}

在上述代码中,我们创建了一个包含所有文件名的列表,并使用foreach循环输出每个文件名。

有时候,我们需要指定文件名和目录名的过滤条件,以便只遍历符合条件的元素。在这种情况下,我们可以使用 DirectoryStream.filter() 方法来对要遍历的元素进行过滤。

例如,以下代码将只遍历目录下的 txt 文件:

Path directoryPath = Paths.get("your-directory-path");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath, "*.txt")) {for (Path file : stream) {System.out.println(file.getFileName());}
}

在上述代码中,我们在 Files.newDirectoryStream() 方法中传递了一个过滤器参数 "*.txt",以表示只遍历文件名后缀为 .txt 的文件。

DirectoryStream 示例1:复制文件夹

以下代码演示了如何使用 DirectoryStream 类实现复制整个文件夹的功能。该程序会递归地遍历源目录下的所有文件和子文件夹,并将它们复制到目标目录中。

import java.io.IOException;
import java.nio.file.*;public class CopyDirectoryExample {public static void main(String[] args) throws IOException {Path sourceDirectoryPath = Paths.get("your-source-directory-path"); // 替换为具体的源目录路径Path targetDirectoryPath = Paths.get("your-target-directory-path"); // 替换为具体的目标目录路径copyDirectory(sourceDirectoryPath, targetDirectoryPath);}public static void copyDirectory(Path sourceDir, Path targetDir) throws IOException {if (!Files.exists(targetDir)) {Files.createDirectories(targetDir);}try (DirectoryStream<Path> stream = Files.newDirectoryStream(sourceDir)) {for (Path file : stream) {Path target = targetDir.resolve(file.getFileName());if (Files.isDirectory(file)) {copyDirectory(file, target);} else {Files.copy(file, target, StandardCopyOption.REPLACE_EXISTING);}}}}
}

在上述代码中,请将 your-source-directory-pathyour-target-directory-path 替换为源目录和目标目录的路径。该程序首先会创建目标目录(如果它不存在的话),然后递归地遍历源目录下的所有文件和子文件夹,并将它们复制到目标目录中。对于每个要复制的文件,程序检查该文件是否是一个目录,如果是,则继续递归调用 copyDirectory 方法;如果不是,则使用 Files.copy() 方法将其复制到目标目录中。

需要注意的是,这个程序还定义了一个文件名过滤器参数 ".DS_Store",以过滤掉 macOS 操作系统中特有的 .DS_Store 文件,因为这个文件在复制到其他操作系统时可能会导致问题。

DirectoryStream 示例2:计算目录下的文件大小

以下代码演示了如何使用 DirectoryStream 类计算指定目录下的所有文件的大小。该程序递归地遍历目录下的所有文件和子文件夹,并统计所有文件的总大小。

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;public class CalculateDirectorySizeExample {public static void main(String[] args) throws IOException {Path directoryPath = Paths.get("your-directory-path"); // 替换为具体的目录路径long totalSize = calculateDirectorySize(directoryPath);System.out.println("Total size: " + totalSize + " bytes");}public static long calculateDirectorySize(Path path) throws IOException {if (!Files.isDirectory(path)) {return Files.size(path);}long totalSize = 0;try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {for (Path file : stream) {totalSize += calculateDirectorySize(file);}}return totalSize;}
}

在上述代码中,请将 your-directory-path 替换为要计算大小的目录路径。该程序首先检查指定路径是否是一个文件,如果是,则返回文件大小;如果不是,则递归遍历目录下的所有文件和子文件夹,并统计所有文件的总大小。

需要注意的是,这个程序也定义了一个文件名过滤器参数 "*.DS_Store",以过滤掉 macOS 操作系统中特有的 .DS_Store 文件。

DirectoryStream 示例3:删除空目录

以下代码演示了如何使用 DirectoryStream 类来删除指定目录下的所有空目录。

import java.io.IOException;
import java.nio.file.*;
import java.util.Stack;public class DeleteEmptyDirectoriesExample {public static void main(String[] args) throws IOException {Path directoryPath = Paths.get("your-directory-path"); // 替换为具体的目录路径deleteEmptyDirectories(directoryPath);}public static void deleteEmptyDirectories(Path path) throws IOException {Stack<Path> stack = new Stack<>();stack.push(path);while (!stack.isEmpty()) {Path dir = stack.pop();try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {boolean isEmpty = true;for (Path child : stream) {if (Files.isDirectory(child)) {stack.push(child);isEmpty = false;} else {isEmpty = false;}}if (isEmpty) {Files.delete(dir);}}}}
}

在上述代码中,请将 your-directory-path 替换为要删除空目录的目录路径。该程序使用 Stack 数据结构来实现深度优先遍历,递归地遍历目录下的所有文件和子文件夹,并判断是否为空目录。如果是,则使用 Files.delete() 删除这个目录。

需要注意的是,由于 Java 的保护机制,删除非空目录会抛出异常。因此,我们需要先确保传入的目录路径确实包含空目录,以防止出现异常情况。