Java在macOS环境下使用Glob模式*.*无法匹配含Unicode字符的路径?
Java在macOS环境下使用Glob模式*.*无法匹配含Unicode字符的路径?
最近在macOS上用Java处理文件匹配时,碰到了个头疼的问题——Java的Glob路径匹配器居然没法正确匹配带某些Unicode符号的文件名。我特意用jshell做了测试,先看正常的匹配情况:
$ jshell | Welcome to JShell -- Version 24 | For an introduction type: /help intro jshell> var matcher = java.nio.file.FileSystems.getDefault().getPathMatcher("glob:*.*") ...> matcher ==> sun.nio.fs.UnixFileSystem$1@2328c243 jshell> matcher.matches(new java.io.File("Article.md").toPath()) ...> $2 ==> true
你看,普通的英文文件名Article.md能正常匹配上,返回true。但如果换成带Unicode字符的文件名,比如Ärticle.md,情况就不对了:
jshell> matcher.matches(new java.io.File("Ärticle.md").toPath()) ...> $3 ==> false
为啥会这样呢?后来查了下才明白,macOS的文件系统默认是用Unicode规范分解形式(NFD)来存储文件名的,而我们在代码里传入的字符串通常是Unicode规范合成形式(NFC)。Java的Glob匹配是直接做字符串比较,这两种形式的Unicode字符虽然视觉上一样,但底层的编码字节不同,自然就匹配失败了。
那怎么解决呢?其实很简单,只需要把路径字符串统一转换成相同的Unicode规范化形式就行。比如我们可以把路径转换成NFD形式,和macOS文件系统存储的格式对齐:
import java.text.Normalizer; import java.nio.file.Path; // 创建带Unicode字符的文件路径 Path unicodeFilePath = new java.io.File("Ärticle.md").toPath(); // 将路径字符串转换为NFD规范形式 String normalizedPathStr = Normalizer.normalize(unicodeFilePath.toString(), Normalizer.Form.NFD); Path normalizedPath = Path.of(normalizedPathStr); // 再用matcher匹配 matcher.matches(normalizedPath); // 这时就能返回true啦
当然,你也可以反过来把Glob模式转换成NFD形式,效果是一样的,核心就是让两边的字符串规范化形式一致。
备注:内容来源于stack exchange,提问作者Michiel Borkent
相关产品推荐
相关产品推荐

