問題代碼
File f = new File("document", "old");
File d = new File("target");
d.mkdir();
d.renameTo(new File("target", "new"));
String[] s = d.list();
for (int i = 0; i < s.length; i++)
System.out.println(s[i]); // 無輸出,甚至拋出 NullPointerException
錯誤分析
- 路徑誤解:
new File("document", "old") 的第一個參數是父目錄路徑,第二個是子路徑。若 "document" 目錄不存在,f 只是一個抽象路徑,不會自動創建目錄。
mkdir() 返回值未檢查:若 "target" 父目錄不存在或無權限,創建失敗返回 false,後續操作無效。
renameTo() 行為不可靠:跨文件系統、目標已存在、Windows 下目標被佔用均會失敗,且不拋異常,只返回 false。
list() 返回 null:當抽象路徑不表示目錄、或目錄不存在、或 I/O 錯誤時返回 null,導致 s.length 拋 NPE。
修正代碼
File targetDir = new File("target");
if (!targetDir.exists()) {
boolean created = targetDir.mkdirs(); // mkdirs 可創建多級目錄
System.out.println("目錄創建:" + created);
}
File newDir = new File("target", "new");
boolean renamed = targetDir.renameTo(newDir);
System.out.println("重命名:" + renamed);
if (newDir.isDirectory()) {
String[] files = newDir.list();
if (files != null) {
for (String file : files) {
System.out.println(file);
}
} else {
System.out.println("目錄為空或讀取失敗");
}
}
最佳實踐
- 優先使用
Files (NIO.2) 替代 File,提供更豐富的異常信息與原子操作。
- 總是檢查
mkdirs()、renameTo()、list() 的返回值。
- 使用
try-with-resources 管理 DirectoryStream 遍歷大目錄。