CodeGym /課程 /JAVA 25 SELF /類別 File、Path、Files:概覽與建立物件

類別 File、Path、Files:概覽與建立物件

JAVA 25 SELF
等級 35 , 課堂 1
開放

1. 類別 File:一切的開始

雖然我們已經得出結論,新專案最好不要使用 File 類別,但仍有大量既有系統在使用它,因此理解並能運用它很重要。File 是在磁碟上表示檔案或目錄的舊方式。但別混淆:File 物件本身不是檔案,只是路徑的「指標」/身分。舉例來說,表達式 File f = new File("hello.txt"); 並不會在磁碟上建立檔案——你只是描述了路徑。

如何建立 File 物件?

import java.io.File;

public class FileDemo {
    public static void main(String[] args) {
        File file = new File("example.txt"); // 相對路徑
        File folder = new File("mydir");     // 目錄

        System.out.println("絕對路徑: " + file.getAbsolutePath());
        System.out.println("檔案是否存在? " + file.exists());
        System.out.println("是檔案嗎? " + file.isFile());
        System.out.println("是目錄嗎? " + folder.isDirectory());
    }
}

要點:
建立 File 物件不會在磁碟上建立檔案。它只是「捷徑」。若要讓檔案實際存在,必須明確地觸發建立(例如寫入資料,或呼叫 file.createNewFile())。

File 類別的主要方法

  • exists() — 檢查檔案/目錄是否存在。
  • isFile() — 是否為檔案(而非資料夾)。
  • isDirectory() — 是否為目錄。
  • getAbsolutePath() — 取得絕對路徑。
  • length() — 檔案大小(位元組)。
  • getName() — 檔案或資料夾名稱。
  • delete() — 刪除檔案/目錄(若為空)。

範例:輸出檔案資訊

File file = new File("example.txt");
System.out.println("名稱: " + file.getName());
System.out.println("路徑: " + file.getAbsolutePath());
System.out.println("大小: " + file.length() + " 位元組");
System.out.println("存在嗎? " + file.exists());

2. 類別 Path:現代的檔案觀

Path 是新的檔案 API(NIO.2,自 Java 7 起)的一部分。它是指向檔案/目錄的路徑抽象,而且路徑不僅可以在本機磁碟上,也可以位於例如 ZIP 封存檔內或遠端資源上(前提是有對應的 provider)。

如果說 File 是舊式紙本地圖,那麼 Path 就是 GPS 導航。

如何建立 Path 物件?

import java.nio.file.Path;
import java.nio.file.Paths;

public class PathDemo {
    public static void main(String[] args) {
        Path path1 = Paths.get("example.txt"); // 相對路徑
        Path path2 = Paths.get("folder", "file.txt"); // 拼接路徑片段

        System.out.println("路徑 1: " + path1.toAbsolutePath());
        System.out.println("路徑 2: " + path2.toAbsolutePath());
    }
}

優點:不必思考分隔符。Paths.get 會依你的作業系統選用正確格式。

FilePath 之間轉換

  • FilePath: file.toPath()
  • PathFile: path.toFile()
File file = new File("test.txt");
Path path = file.toPath();

Path anotherPath = Paths.get("data.txt");
File anotherFile = anotherPath.toFile();

路徑操作:resolverelativizenormalize

路徑拼接(resolve

Path dir = Paths.get("myfolder");
Path file = dir.resolve("notes.txt"); // myfolder/notes.txt
System.out.println(file); // myfolder/notes.txt

相對路徑(relativize

Path pathA = Paths.get("folderA/file1.txt");
Path pathB = Paths.get("folderA/subfolder/file2.txt");
Path relative = pathA.relativize(pathB);
System.out.println(relative); // ../subfolder/file2.txt

路徑正規化(normalize

Path messy = Paths.get("folder/../folder/file.txt");
Path clean = messy.normalize();
System.out.println(clean); // folder/file.txt

範例:構建檔案路徑

Path home = Paths.get(System.getProperty("user.home"));
Path docs = home.resolve("Documents");
Path myFile = docs.resolve("myfile.txt");
System.out.println("檔案路徑: " + myFile.toAbsolutePath());

3. 類別 Files:你的瑞士軍刀

Files 類別位於 java.nio.file 套件中——基於 Path 的檔案與目錄操作靜態工具方法集合。它幾乎無所不能:檢查存在、建立/刪除、讀/寫、複製/移動、取得屬性與遍歷目錄樹。

Files 類別的主要方法

  • Files.exists(path) — 檢查檔案/目錄是否存在。
  • Files.isDirectory(path) — 是否為目錄。
  • Files.size(path) — 檔案大小。
  • Files.createFile(path) — 建立檔案。
  • Files.createDirectory(path) — 建立目錄。
  • Files.delete(path) — 刪除檔案/目錄。
  • Files.copy(src, dest) — 複製檔案。
  • Files.move(src, dest) — 移動/重新命名。
  • Files.getLastModifiedTime(path) — 最後修改時間。
  • Files.readAllBytes(path) — 讀取整個檔案為位元組陣列。
  • Files.readAllLines(path) — 讀取文字檔的所有行。
  • Files.write(path, bytes) — 寫入位元組到檔案。

範例:檢查檔案

import java.nio.file.*;

public class FilesDemo {
    public static void main(String[] args) {
        Path path = Paths.get("example.txt");

        System.out.println("檔案存在嗎? " + Files.exists(path));
        System.out.println("這是目錄嗎? " + Files.isDirectory(path));

        if (Files.exists(path)) {
            try {
                System.out.println("檔案大小: " + Files.size(path) + " 位元組");
            } catch (Exception e) {
                System.out.println("取得大小時發生錯誤: " + e.getMessage());
            }
        }
    }
}

4. 實作:建立物件、輸出屬性

為檔案與目錄建立物件

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;

public class CompareDemo {
    public static void main(String[] args) {
        // 舊方法
        File oldFile = new File("test.txt");
        File oldDir = new File("mydir");

        // 新方法
        Path newFile = Paths.get("test.txt");
        Path newDir = Paths.get("mydir");

        System.out.println("=== File API ===");
        System.out.println("檔案: " + oldFile.getAbsolutePath());
        System.out.println("存在嗎? " + oldFile.exists());
        System.out.println("是檔案嗎? " + oldFile.isFile());
        System.out.println("是目錄嗎? " + oldDir.isDirectory());

        System.out.println("\n=== Path API ===");
        System.out.println("檔案: " + newFile.toAbsolutePath());
        System.out.println("存在嗎? " + java.nio.file.Files.exists(newFile));
        System.out.println("是檔案嗎? " + java.nio.file.Files.isRegularFile(newFile));
        System.out.println("是目錄嗎? " + java.nio.file.Files.isDirectory(newDir));
    }
}

輸出檔案屬性

import java.nio.file.*;

public class FileProperties {
    public static void main(String[] args) {
        Path path = Paths.get("test.txt");

        System.out.println("絕對路徑: " + path.toAbsolutePath());
        System.out.println("檔名: " + path.getFileName());
        System.out.println("父目錄: " + path.getParent());

        if (Files.exists(path)) {
            try {
                System.out.println("大小: " + Files.size(path) + " 位元組");
                System.out.println("最後修改: " + Files.getLastModifiedTime(path));
            } catch (Exception e) {
                System.out.println("取得資訊時發生錯誤: " + e.getMessage());
            }
        } else {
            System.out.println("找不到檔案。");
        }
    }
}

5. 比較:File vs Path/Files

功能 File (java.io) Path + Files (java.nio.file)
路徑表現 僅本機磁碟 本機磁碟、ZIP、網路資源
路徑拼接 以斜線手動串接 方便使用 resolve
存在性檢查 exists() Files.exists(path)
讀寫內容 是(Files.readAll...Files.write
取得屬性 基本(length()lastModified() 進階屬性與視圖
相容性 適用所有 Java 版本 Java 7 以上
符號連結支援 受限 完整支援

簡述:何時使用哪一套?

  • 新專案——請使用 PathFiles
  • 維護舊程式碼——有時仍需與 File 搭配。

6. 實用細節

相對與絕對路徑

相對路徑:相對於目前工作目錄的路徑;絕對路徑:自檔案系統根目錄起的完整路徑。

Path relative = Paths.get("data", "file.txt");
Path absolute = relative.toAbsolutePath();
System.out.println("絕對路徑: " + absolute);

跨平台性

PathFiles 會考量作業系統的特性(分隔符、編碼等)。不要手動書寫像 "C:\\folder\\file.txt" 這樣的路徑——請使用 Paths.getresolve

FilePath 之間轉換

如果你有以 File 為主的舊碼,很容易切換到新 API:

File legacy = new File("legacy.txt");
Path modern = legacy.toPath();
if (Files.exists(modern)) {
    // 現在即可使用 NIO.2 的所有功能
}

檢查檔案是否存在

Path path = Paths.get("notes.txt");
if (Files.exists(path)) {
    System.out.println("找到檔案!");
} else {
    System.out.println("檔案不存在。");
}

7. 迷你實作:建立並檢查檔案與目錄

import java.nio.file.*;

public class MiniPractice {
    public static void main(String[] args) throws Exception {
        Path dir = Paths.get("demo_dir");
        Path file = dir.resolve("hello.txt");

        // 若目錄不存在則建立
        if (!Files.exists(dir)) {
            Files.createDirectory(dir);
            System.out.println("已建立目錄: " + dir.toAbsolutePath());
        }

        // 若檔案不存在則建立
        if (!Files.exists(file)) {
            Files.createFile(file);
            System.out.println("已建立檔案: " + file.toAbsolutePath());
        }

        // 輸出屬性
        System.out.println("檔案存在嗎? " + Files.exists(file));
        System.out.println("是檔案嗎? " + Files.isRegularFile(file));
        System.out.println("大小: " + Files.size(file) + " 位元組");

        // 刪除檔案與目錄(可選)
        Files.delete(file);
        Files.delete(dir);
        System.out.println("已刪除檔案與目錄。");
    }
}

8. 使用 File/Path/Files 時的常見錯誤

錯誤 1:混淆 File 與 Path。 許多新手會嘗試把 Files 的方法用在 File 物件上。記住:Files.* 適用於 Path。如果你手上是 File,先呼叫 file.toPath()。

錯誤 2:以為建立 File 或 Path 物件會建立檔案。 路徑物件是捷徑,而不是真實檔案。要建立檔案請使用 Files.createFile(path) 或進行資料寫入。

錯誤 3:以字串手動拼裝路徑。 不要寫 "folder/file.txt""folder\\file.txt"。請使用 Paths.get(...) 與 resolve(...)。這更安全且可跨平台。

錯誤 4:忽略例外。 檔案操作會丟出 IOException 等例外。請透過 try-catch 處理,或向上拋出(throws)。

錯誤 5:先用 File.exists() 檢查,接著卻用 Path 操作。 盡量維持一致風格:既然開始用 Path,就請使用 Files.exists(path) 與其他 Files 方法。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION