java.io.File 是 Java 操作文件系統元數據(路徑、屬性、權限、目錄結構)的核心類,不負責數據內容讀寫(那是 Stream/Channel 的事)。掌握其構造器、判斷、獲取、遍歷、過濾、遞歸、重命名/移動、跨平台路徑語義,是文件管理功能開發的基礎。本文提供全 API 覆蓋的實戰代碼模板。
// 1. 路徑字符串 (相對/絕對)
File f1 = new File("data/config.json");
File f2 = new File("/home/user/data/config.json");
File f3 = new File("C:\\Users\\user\\data\\config.json"); // Windows 絕對路徑
// 2. 父路徑 + 子路徑 (推薦:語義清晰、自動處理分隔符)
File dir = new File("/home/user/data");
File f4 = new File(dir, "config.json");
// 3. 父 File + 子路徑
File f5 = new File(dir, "subdir/config.json");
// 4. 跨平台分隔符
String sep = File.separator; // "\" 或 "/"
String pathSep = File.pathSeparator; // ";" 或 ":"
File f6 = new File("home" + sep + "user" + sep + "data"); // 手動拼接 (不推薦)
// 5. URI 轉換 (支援 file:// 協議)
File f7 = new File(URI.create("file:///home/user/data/config.json"));
最佳實踐:優先使用 new File(parent, child) 或 Java 7+ Paths.get() / Path.resolve(),避免手動拼接字符串。
File file = new File("target.txt");
File dir = new File("target/dir");
// 創建文件 (原子性:不存在才創建)
boolean created = file.createNewFile(); // 父目錄必須存在
// 創建目錄
dir.mkdir(); // 單層,父目錄必須存在
dir.mkdirs(); // 多層遞歸創建 (推薦)
// 刪除
file.delete(); // 文件/空目錄,失敗返回 false
file.deleteOnExit(); // JVM 退出時刪除 (臨時文件常用)
// 遞歸刪除非空目錄 (Java 7+ 推薦 Files.walkFileTree)
public static void deleteRecursive(File f) throws IOException {
if (f.isDirectory()) {
Files.walkFileTree(f.toPath(), new SimpleFileVisitor() {
@Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file); return FileVisitResult.CONTINUE;
}
@Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir); return FileVisitResult.CONTINUE;
}
});
} else {
Files.deleteIfExists(f.toPath());
}
}
File f = new File("test.txt");
System.out.println("exists: " + f.exists());
System.out.println("isFile: " + f.isFile());
System.out.println("isDirectory: " + f.isDirectory());
System.out.println("isHidden: " + f.isHidden());
System.out.println("canRead: " + f.canRead());
System.out.println("canWrite: " + f.canWrite());
System.out.println("canExecute: " + f.canExecute()); // Unix 執行權限
System.out.println("isAbsolute: " + f.isAbsolute());
System.out.println("getName: " + f.getName()); // 文件名
System.out.println("getPath: " + f.getPath()); // 構造時路徑
System.out.println("getAbsolutePath: " + f.getAbsolutePath()); // 絕對路徑
System.out.println("getParent: " + f.getParent()); // 父目錄路徑
System.out.println("length: " + f.length()); // 字節大小
System.out.println("lastModified: " + new Date(f.lastModified())); // 修改時間
// 重命名/移動 (同分區即重命名,跨分區實為複製+刪除)
File dest = new File("renamed.txt");
boolean ok = f.renameTo(dest); // 目標存在會失敗,跨文件系統行為不定
// 列出根分區
File[] roots = File.listRoots(); // Windows: C:\, D:\ Linux: /
for (File root : roots) {
System.out.println(root + " free: " + root.getFreeSpace() + " total: " + root.getTotalSpace());
}
File dir = new File("src/main/java");
String[] names = dir.list(); // 返回文件名數組 (不含路徑),目錄不存在返回 null
File[] files = dir.listFiles(); // 返回 File 數組,便於鏈式調用
// 只列出 .java 文件
File[] javaFiles = dir.listFiles((d, name) -> name.endsWith(".java"));
// 正則過濾
File[] testFiles = dir.listFiles((d, name) -> name.matches(".*Test\\.java"));
// 大於 1MB 的文件
File[] largeFiles = dir.listFiles(f -> f.isFile() && f.length() > 1_000_000);
// 目錄 + 文件名模式
File[] filtered = dir.listFiles(f -> f.isDirectory() || f.getName().endsWith(".xml"));
public static void walk(File dir, Consumer action) {
File[] files = dir.listFiles();
if (files == null) return; // 無權限或非目錄
for (File f : files) {
action.accept(f);
if (f.isDirectory()) walk(f, action);
}
}
// 使用
walk(new File("D:/projects"), f -> {
if (f.getName().endsWith(".java")) System.out.println(f.getAbsolutePath());
});
Files.walkFileTree(Paths.get("D:/projects"), new SimpleFileVisitor() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (file.toString().endsWith(".java")) {
System.out.println(file);
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
System.err.println("無法訪問: " + file + " " + exc.getMessage());
return FileVisitResult.CONTINUE; // 跳過繼續
}
});
try (Stream stream = Files.walk(Paths.get("D:/projects"), 10)) { // 最大深度 10
stream.filter(p -> p.toString().endsWith(".java"))
.forEach(System.out::println);
}
public class FileMover {
public static void main(String[] args) throws IOException {
Path sourceRoot = Paths.get("D:/source");
Path targetRoot = Paths.get("C:/jad");
Files.walkFileTree(sourceRoot, new SimpleFileVisitor() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (file.toString().endsWith(".java")) {
Path target = targetRoot.resolve(sourceRoot.relativize(file))
.resolveSibling(file.getFileName().toString().replace(".java", ".jad"));
try {
Files.createDirectories(target.getParent());
Files.move(file, target, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Moved: " + file + " -> " + target);
} catch (IOException e) {
System.err.println("Move failed: " + file + " " + e);
}
}
return FileVisitResult.CONTINUE;
}
});
}
}
Java 7+ java.nio.file.Path 替代 File 進行路徑運算,File.toPath() 無縫轉換。
Path base = Paths.get("/home/user");
Path file = base.resolve("docs").resolve("readme.txt"); // /home/user/docs/readme.txt
Path relativized = base.relativize(file); // docs/readme.txt
Path normalized = Paths.get("/home/../user/./docs").normalize(); // /user/docs
// 迭代路徑組件
for (Path part : file) System.out.println(part); // home, user, docs, readme.txt
// 文件系統操作仍用 Files 工具類
Files.createDirectories(file.getParent());
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
File 管元數據,Files/Paths 管操作與路徑運算,Stream/Channel 管數據內容。new File(parent, child),路徑運算用 Path.resolve/relativize/normalize。Files.walkFileTree (健壯) 或 Files.walk (Stream 簡潔)。FileFilter/FilenameFilter。Files 配合 FileVisitor。