应使用结合路径分隔符与点位置判断的逻辑提取扩展名:先定位文件名起始索引,再确认最后一个点位于文件名内部且不为开头或结尾,最后截取子串;否则返回空字符串。

直接用 String.substring() 配合 lastIndexOf(".") 提取扩展名,看似简单,但容易出错——比如路径不含点、是目录名(如 "src/main")、含多个点(如 "archive.tar.gz"),或以点开头(如 ".gitignore")。要精准提取“真正的文件扩展名”,关键在于:**只取最后一个点之后、且该点不能是路径分隔符后的第一个字符(即排除隐藏文件名本身)**。
判断是否存在有效扩展名分隔点
先用 lastIndexOf(".") 找到最后一个点的位置,但必须确认这个点出现在文件名部分,而非目录名中。最可靠的方式是结合 lastIndexOf(File.separator)(或 lastIndexOf("/")、lastIndexOf("\"))来定位文件名起始位置:
- 计算文件名起始索引:
int fileNameStart = path.lastIndexOf(File.separatorChar) + 1; - 获取最后一个点在整串中的位置:
int dotIndex = path.lastIndexOf("."); - 只有当
dotIndex > fileNameStart时,该点才属于文件名内部,才可能构成扩展名
排除隐藏文件和纯点名等边界情况
即使点在文件名范围内,也要防范非法情形:
- 如果
dotIndex == fileNameStart,说明文件名以点开头(如"/home/.config"),这不是扩展名,而是隐藏文件或目录,应忽略 - 如果
dotIndex == path.length() - 1,说明点在末尾(如"readme."),无实际扩展名,返回空字符串或 null - 确保
dotIndex不为 -1(即确实存在点)
安全截取并返回扩展名
满足上述条件后,用 substring(dotIndex + 1) 即可得到扩展名:
- 例如:
"C:\Users\doc.pdf"→fileNameStart = 12,dotIndex = 16,substring(17)→"pdf" - 例如:
"/var/log/app.log.202405"→ 最后一个点在".202405"前,结果为"202405"(符合常规理解) - 若想支持多级扩展(如
"file.tar.gz"),需额外逻辑(如正则匹配常见归档后缀),标准 substring + lastIndexOf 仅能取最后一段
封装成可复用的方法
推荐写成工具方法,兼顾健壮性与简洁性:
public static String getExtension(String path) {
if (path == null || path.isEmpty()) return "";
int sepIndex = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\'));
int dotIndex = path.lastIndexOf('.');
int fileNameStart = sepIndex == -1 ? 0 : sepIndex + 1;
if (dotIndex <= fileNameStart || dotIndex == path.length() - 1) {
return "";
}
return path.substring(dotIndex + 1);
}

















