382. Java IO API - 使用 Java 查找匹配文件

0 阅读1分钟

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 实现方式
排除子目录-prunepreVisitDirectory() 中返回 SKIP_SUBTREE
跟随符号链接-L使用四参的 walkFileTree(..., EnumSet.of(FOLLOW_LINKS), ...)
处理循环链接检测 FileSystemLoopExceptionvisitFileFailed() 中处理异常

📦 命令行模拟调用示例:

$ 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 返回值可精细控制遍历流程(继续、跳过、终止等)