File操作需先调用exists()再isFile()/isDirectory();lastModified()和length()精度受限且目录length恒为0;list()/listFiles()异常时返回null而非抛异常;mkdirs()无原子性且不支持权限设置;推荐优先使用java.nio.file。

File.exists() 和 isFile()/isDirectory() 的判断顺序很重要
直接调用 isFile() 或 isDirectory() 前必须先确认路径存在,否则返回 false——这不表示“不是文件”,而是“不存在或无法访问”。常见误判就出在这里。
- 先用
exists()排除路径不存在、权限不足、符号链接断裂等情况 - 再用
isFile()或isDirectory()区分类型;若exists()为true但两个都返回false,大概率是符号链接指向了无效路径,或遇到特殊文件系统(如某些 NFS 挂载) - Windows 下对隐藏文件或受保护的系统目录(如
C:\System Volume Information)可能抛SecurityException,需捕获处理
lastModified() 和 length() 的精度与一致性问题
lastModified() 返回毫秒时间戳,但底层文件系统可能只保留到秒级(如 FAT32、部分网络存储),多次调用可能看到相同值;length() 对目录始终返回 0,不是子项数量也不是磁盘占用。
- 不要用
lastModified()做高精度轮询——改用java.nio.file.WatchService - 获取目录实际大小需递归遍历,
length()完全不可靠 - 跨平台注意:Linux ext4 和 macOS APFS 支持纳秒精度,但
File类不暴露,要用Files.readAttributes(path, BasicFileAttributes.class)
list() 和 listFiles() 在权限/编码异常时静默失败
当目录不可读、路径含非法字符(如 Windows 路径中的 ?、*)、或默认字符集无法解码文件名(常见于 Linux 中文文件名 + JVM 启动参数未设 -Dfile.encoding=UTF-8),list() 和 listFiles() 都会返回 null,而非抛异常。
- 务必检查返回值是否为
null,不能直接遍历 - 推荐改用
Files.list(Paths.get(dirPath)),它会在出错时明确抛IOException - 若必须用
File,建议配合File.canRead()提前校验
mkdirs() 不保证原子性,且无法设置初始权限
mkdirs() 会逐级创建父目录,但中间某层创建成功后崩溃,可能导致残留空目录;更重要的是,它完全不支持指定权限(如 0755),在 Linux/macOS 上新建目录默认权限受 umask 影响,不可控。
立即学习“Java免费学习笔记(深入)”;
- 多线程环境下,两个线程同时调用
mkdirs()可能都返回true,但只有一个真正创建成功(另一个发现已存在) - 需要精确权限控制时,必须用
Files.createDirectories(path, attrs),其中attrs可传入PosixFilePermissions.asFileAttribute(...) - 注意:Windows 不支持 POSIX 权限,
createDirectories会忽略相关属性
java.nio.file 是绕不开的替代方案——尤其是涉及符号链接解析、权限控制、或需要明确异常语义的场景。


















