java.io.File 核心功能
File 類代表文件/目錄路徑抽象,**不負責內容讀寫** (那是流的事),負責:元數據查詢、重命名/刪除、目錄列表、路徑轉換。
構造方法
new File(String pathname) // 絕對/相對路徑
new File(String parent, String child) // 父路徑 + 子路徑
new File(File parent, String child) // 父 File 對象 + 子路徑
new File(URI uri) // file:// 協議 URI
核心查詢方法
| 方法 | 返回 | 說明 |
exists() | boolean | 文件/目錄是否存在 |
isFile() | boolean | 是否為文件 |
isDirectory() | boolean | 是否為目錄 |
canRead()/canWrite() | boolean | 權限檢查 (受 OS/文件系統 ACL 影響) |
length() | long | 文件大小 (字節),目錄返回 0 |
lastModified() | long | 最後修改時間 (毫秒時間戳) |
getName() | String | 文件/目錄名 (不含路徑) |
getParent() | String | 父目錄路徑 (無則 null) |
getPath() | String | 構造時的路徑 |
getAbsolutePath() | String | 絕對路徑 (解析相對路徑) |
getCanonicalPath() | String | 規範路徑 (解析 . .. 符號鏈接),可能拋 IOException |
修改操作
boolean renameTo(File dest) // 重命名/移動 (跨文件系統可能失敗)
boolean delete() // 刪除 (目錄必須為空)
boolean mkdir() // 創建單級目錄
boolean mkdirs() // 創建多級目錄 (含父目錄)
boolean createNewFile() // 原子創建空文件 (不存在時)
目錄遍歷與過濾
傳統列表方法
// 1. 簡單列表
String[] names = file.list(); // 僅名稱,null 表示非目錄/IO錯誤
// 2. FilenameFilter 過濾名稱
String[] htmlFiles = file.list((dir, name) -> name.endsWith(".html"));
// 3. FileFilter 過濾 File 對象 (可判斷是否目錄、大小等)
File[] subDirs = file.listFiles(f -> f.isDirectory());
FilenameFilter 經典實現
public class ExtensionFilter implements FilenameFilter {
private final String extension; // 帶點 ".html"
public ExtensionFilter(String ext) {
this.extension = ext.startsWith(".") ? ext : "." + ext;
}
@Override public boolean accept(File dir, String name) {
return name.endsWith(extension);
}
}
// 使用
File dir = new File("/web");
String[] pages = dir.list(new ExtensionFilter("html"));
NIO.2 現代化 API (Java 7+) — 強烈推薦新代碼使用
Path 替代 File
Path path = Paths.get("/web", "index.html"); // 自動處理分隔符
Path path2 = FileSystems.getDefault().getPath("/web/index.html");
Files 工具類核心操作
| 操作 | API 示例 |
| 讀取所有行 | List lines = Files.readAllLines(path, StandardCharsets.UTF_8); |
| 流式處理大文件 | try (Stream s = Files.lines(path)) { ... } |
| 寫入 | Files.write(path, lines, StandardCharsets.UTF_8, CREATE, TRUNCATE_EXISTING); |
| 複製/移動 | Files.copy(src, dest, REPLACE_EXISTING); Files.move(src, dest, ATOMIC_MOVE); |
| 刪除 | Files.delete(path); Files.deleteIfExists(path); |
| 屬性讀取 | Files.size(path); Files.getLastModifiedTime(path); Files.isDirectory(path); |
| 目錄遍歷 (深度優先) | Files.walkFileTree(root, new SimpleFileVisitor<>() { ... }); |
| 目錄流 (淺層) | try (Stream s = Files.list(dir)) { ... } |
| 查找文件 | Files.find(root, maxDepth, (p, a) -> p.toString().endsWith(".log")); |
文件屬性視圖
// 基本屬性
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
attrs.creationTime(); attrs.lastModifiedTime(); attrs.size(); attrs.isDirectory();
// POSIX 權限 (Linux/macOS)
PosixFileAttributes posix = Files.readAttributes(path, PosixFileAttributes.class);
posix.permissions(); // Set
posix.owner(); posix.group();
// DOS 屬性 (Windows)
DosFileAttributes dos = Files.readAttributes(path, DosFileAttributes.class);
dos.isHidden(); dos.isReadOnly(); dos.isSystem();
File vs Path 遷移對照表
| File 方法 | Path/Files 替代 |
file.exists() | Files.exists(path) |
file.isDirectory() | Files.isDirectory(path) |
file.length() | Files.size(path) |
file.lastModified() | Files.getLastModifiedTime(path).toMillis() |
file.list() | Files.list(dir).map(Path::getFileName).toArray(String[]::new) |
file.listFiles() | Files.list(dir).toArray(Path[]::new) |
file.mkdirs() | Files.createDirectories(path) |
file.delete() | Files.deleteIfExists(path) |
file.renameTo(dest) | Files.move(src, dest, REPLACE_EXISTING) |
最佳實踐總結
- 新代碼優先用 Path/Files:異常處理統一 (IOException)、符號鏈接支持、原子操作、流式處理、屬性視圖豐富
- 舊代碼維護:File 仍可用,但注意
list() 返回 null 而非空數組、renameTo() 跨卷失敗等坑
- 路徑拼接:
Paths.get(base, "sub", "file") 或 base.resolve("sub/file")
- 臨時文件:
Files.createTempFile(prefix, suffix) (安全、自動清理掛鉤可選)
- 文件監聽:
WatchService (目錄變更通知),替代輪詢
總結
java.io.File 是歷史產物,功能局限且 API 設計有缺陷 (null 返回、無符號鏈接支持、無原子操作)。NIO.2 (Path/Files) 是現代 Java 文件系統操作的標準,提供一致異常模型、豐富屬性視圖、流式處理、原子操作、文件監聽。遷移指南:逐模塊替換,新代碼禁用 File。