应使用paths.get(path).getfilename().tostring()先提取纯文件名,再对其调用lastindexof(".")获取扩展名,以避免路径分隔符干扰;需判断dotindex>0确保点不在开头,从而正确处理无扩展名、隐藏文件等边界情况。

直接用 String.substring() 配合 lastIndexOf(".") 提取扩展名,关键在于定位最后一个点号的位置,并确保它不是路径分隔符(如 或 /)之后的点——否则可能误把文件夹名里的点当成扩展名分隔符。
先找最后一个点的位置,再验证它是否属于文件名部分
仅靠 lastIndexOf(".") 不够安全。例如路径 "C:/data.report/config.txt" 中,最后一个点在 "report/" 里,但真正扩展名是 "txt"。所以得从末尾开始,跳过路径分隔符,再找点:
- 用
lastIndexOf(File.separator)找到最后一个路径分隔符位置(Windows 是"\",Unix/Linux/macOS 是"/") - 如果没找到分隔符,就从头开始找点;否则,只在分隔符之后的子串里找点
- 推荐统一用
Paths.get(path).getFileName().toString()先提取纯文件名,再对它调用lastIndexOf("."),更可靠
安全提取扩展名的标准写法
以下代码兼顾常见路径格式和边界情况(如无扩展名、以点开头的文件名、纯点或空文件名):
String path = "D:\docs\notes.tar.gz";
String fileName = Paths.get(path).getFileName().toString();
int dotIndex = fileName.lastIndexOf('.');
if (dotIndex > 0 && dotIndex <h3>为什么不能直接 path.lastIndexOf(".")?</h3><p>因为路径中可能出现多个点,且点可能出现在目录名里:</p>
-
"./src/main.java/Hello.java"→ 最后一个点在"main.java/"中,但实际文件是"Hello.java" -
"/home/user/.config"→lastIndexOf(".") == 12,但这是隐藏目录名,不是扩展名 -
"archive."→ 以点结尾,substring(dotIndex + 1)会返回空字符串,合理
补充:处理多级扩展名(如 .tar.gz)
标准 substring + lastIndexOf 只能取最后一段("gz")。若需完整扩展名("tar.gz"),需额外逻辑:
- 先获取文件名(不含路径)
- 从末尾向前扫描,识别连续的“点+字母数字”段,直到遇到非扩展名结构(如两个连续点、点在开头、点后为空)
- 或用正则:
fileName.replaceFirst("^(.*?)(?:\.[a-zA-Z0-9]+)+$", "$1")配合替换反推,但 substring 方案更轻量










