File.length() 返回0L是设计行为而非bug,发生在文件不存在、是目录、无读取权限或被独占锁定时;必须用exists()、isFile()、canRead()三重校验确保结果可信。

File.length() 能直接返回文件大小,但只对普通文件有效,对目录、不存在的路径或无读取权限的文件会静默返回 0L——这不是 bug,是设计行为,必须主动校验。
为什么 File.length() 有时返回 0
它不抛异常,也不提示错误,只在以下情况返回 0L:
- 文件不存在(
file.exists() == false) - 路径是目录(
file.isDirectory() == true) - 当前进程无读取权限(Linux/macOS 常见,Windows 可能表现不同)
- 文件被其他进程独占锁定(如 Excel 正在编辑中)
别依赖返回值非零就认定成功;必须先用 file.isFile() 排除目录,再用 file.canRead() 确认可读。
安全获取文件大小的最小检查组合
仅三步即可覆盖绝大多数误判场景:
立即学习“Java免费学习笔记(深入)”;
- 调用
file.exists()—— 排除路径不存在 - 调用
file.isFile()—— 排除目录、符号链接(Java 7+ 中isDirectory()对软链可能返回 false,但isFile()更可靠) - 调用
file.canRead()—— 排除权限/锁定问题
三者全为 true 时,file.length() 的结果才可信。示例:
File file = new File("/path/to/data.log");
if (file.exists() && file.isFile() && file.canRead()) {
long size = file.length(); // 此时 size 是真实字节数
} else {
// 处理:日志警告、抛 IllegalArgumentException 或 fallback 到 Files.size()
}
替代方案:Files.size() 的优势与代价
Java 7+ 推荐用 Files.size(Path),它会在上述任一条件不满足时明确抛出异常(IOException 或 SecurityException),便于区分问题类型:
- 路径不存在 →
NoSuchFileException - 是目录 →
IOException(消息含 "Is a directory") - 无权限 →
AccessDeniedException
但注意:它比 File.length() 略慢(涉及 Path 构建和更重的底层调用),高并发统计大量小文件时差异明显。若已确定路径合法且稳定,File.length() 仍是轻量首选。
真正容易被忽略的是:File.length() 不保证原子性——如果文件正在被写入,返回值可能是中间状态。需要精确大小时(如断点续传),得配合文件锁或业务层同步机制,不能只靠一次 length() 调用。


















