382. Java IO API - 使用 Java 查找匹配文件
你是否在 Shell 中用过这样的命令?
$ ls *.html
这就是所谓的通配符匹配(Pattern Matching),用 * 匹配任意数量的字符,快速列出所有 .html 文件。这种功能在脚本编程中非常常见,而 Java 也支持类似的方式 —— 借助 java.nio.file 包中的 PathMatcher 接口。
🧰 获取 PathMatcher:查找匹配规则的起点
Java 通过 FileSystems.getDefault().getPathMatcher(...) 方法来获取匹配器。格式如下:
String pattern = "*.html";
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
-
"glob:*.html"表示使用 glob 语法 来匹配所有以.html结尾的文件。 -
除了 glob,你也可以使用 正则表达式(regex):
getPathMatcher("regex:^.*\\.(html|htm)$")
📦 glob vs. regex:两种模式的对比
| 模式类型 | 特点 | 示例 |
|---|---|---|
glob | 类似 Shell 通配符,易用、直观 | *.{java,class} |
regex | 强大灵活,语法更复杂 | `^.*.(java |
✅ 示例:匹配 .java 或 .class 文件
PathMatcher matcher =
FileSystems.getDefault().getPathMatcher("glob:*.{java,class}");
Path filename = Paths.get("Example.java");
if (matcher.matches(filename.getFileName())) {
System.out.println("✅ Matched: " + filename);
}
注意:传入 matcher.matches(...) 的通常是 filename.getFileName(),否则路径前缀也会参与匹配。
🌲 结合 walkFileTree 实现递归查找
我们经常会遇到类似“某个文件到底在哪个目录下?”的问题。这时可以结合 Files.walkFileTree() 实现文件树递归查找匹配文件。
📘 示例:Find 实现(类似 UNIX find 命令)
public class Finder extends SimpleFileVisitor<Path> {
private final PathMatcher matcher;
public Finder(String pattern) {
matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (matcher.matches(file.getFileName())) {
System.out.println("📄 Found: " + file);
}
return FileVisitResult.CONTINUE;
}
}
🧪 调用方式:
Path startDir = Paths.get(".");
String pattern = "*.html";
Finder finder = new Finder(pattern);
Files.walkFileTree(startDir, finder);
⚙️ 可扩展功能举例:
| 功能 | 类似 UNIX 命令 | Java 实现方式 |
|---|---|---|
| 排除子目录 | -prune | 在 preVisitDirectory() 中返回 SKIP_SUBTREE |
| 跟随符号链接 | -L | 使用四参的 walkFileTree(..., EnumSet.of(FOLLOW_LINKS), ...) |
| 处理循环链接 | 检测 FileSystemLoopException | 在 visitFileFailed() 中处理异常 |
📦 命令行模拟调用示例:
$ java Find . -name "*.html"
在 Java 程序中接收参数:
public static void main(String[] args) throws IOException {
if (args.length != 3 || !args[1].equals("-name")) {
System.err.println("Usage: java Find <start-path> -name \"<glob-pattern>\"");
System.exit(1);
}
Path startingPath = Paths.get(args[0]);
String pattern = args[2];
Finder finder = new Finder(pattern);
Files.walkFileTree(startingPath, finder);
}
🔚 小结:文件查找实用技巧
| 技术点 | 用途 |
|---|---|
PathMatcher | 用来判断文件是否匹配某个模式 |
glob: | 简洁易读,适用于文件扩展名匹配 |
regex: | 更复杂匹配(如特定命名规则) |
Files.walkFileTree() | 遍历整个文件树,配合 Finder 查找文件 |
FileVisitResult 返回值 | 可精细控制遍历流程(继续、跳过、终止等) |