首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java File 類完全指南:文件/目錄操作、遍歷過濾、遞歸搜索、移動重命名、跨平台路徑處理

     編輯:Java 程式設計入門

前言

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());
}

四、目錄遍歷與過濾

1. 基礎列表

File dir = new File("src/main/java");
String[] names = dir.list(); // 返回文件名數組 (不含路徑),目錄不存在返回 null
File[] files = dir.listFiles(); // 返回 File 數組,便於鏈式調用

2. FilenameFilter (按名稱過濾)

// 只列出 .java 文件
File[] javaFiles = dir.listFiles((d, name) -> name.endsWith(".java"));

// 正則過濾
File[] testFiles = dir.listFiles((d, name) -> name.matches(".*Test\\.java"));

3. FileFilter (按文件對象過濾,功能更強)

// 大於 1MB 的文件
File[] largeFiles = dir.listFiles(f -> f.isFile() && f.length() > 1_000_000);

// 目錄 + 文件名模式
File[] filtered = dir.listFiles(f -> f.isDirectory() || f.getName().endsWith(".xml"));

五、遞歸遍歷全盤/指定目錄

方案 A: 遞歸方法 (教學、簡單邏輯)

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());
});

方案 B: Files.walkFileTree (生產級、健壯、支援屬性、錯誤處理)

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; // 跳過繼續
    }
});

方案 C: Files.walk (Stream API, Java 8+)

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;
            }
        });
    }
}

七、跨平台路徑處理最佳實踐 (Path API)

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 簡潔)。
  • 過濾用 Lambda 實現 FileFilter/FilenameFilter。
  • 刪除非空目錄、移動跨分區、權限檢查、符號鏈接處理,務必用 Files 配合 FileVisitor。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved