CodeGym /課程 /C# SELF /靜態類別 File

靜態類別 FileDirectory

C# SELF
等級 39 , 課堂 0
開放

1. 介紹

直接操作流(StreamReader, StreamWriter, FileStream)非常有用,特別是當你需要在低層級控制讀寫流程時:例如,分塊寫入或分段處理大型檔案。

但在實務上,很多情境只是想知道:「這個檔案存在嗎?」「把檔案從這裡複製到那裡」「刪除檔案」「取得資料夾中所有 .txt 檔案的清單」等等。針對這類工作,Microsoft 提供了兩個通用工具:靜態類別 FileDirectory。靜態的意思是你不需要建立實例,直接用類別名稱呼叫方法。

生活類比

如果流是你拿著鉛筆,一筆一畫地在紙上寫字,那 FileDirectory 就像你的桌子和抽屜:你可以「瞬間」打開一個抽屜(Directory),從裡面拿出一張紙(File.ReadAllText),丟掉那張紙(File.Delete),甚至把整個抽屜搬到房間另一邊(Directory.Move)。簡單的事就用簡單的方法。

2. 類別 File:是什麼、有什麼用

File 提供了一組方便的靜態方法,涵蓋常見的檔案操作。

最常用的方法

方法 說明
File.Exists(path)
檢查路徑上是否存在檔案
File.ReadAllText(path)
將整個檔案讀成文字
File.ReadAllLines(path)
把檔案的所有行讀成陣列
File.WriteAllText(path, text)
覆寫檔案,寫入文字
File.AppendAllText(path, text)
在檔案末尾追加文字
File.Copy(source, destination)
複製檔案
File.Delete(path)
刪除檔案
File.Move(source, destination)
移動或重新命名檔案
File.Open/Read/Write/Create
打開流以進行複雜操作

快速範例:檢查檔案並讀取

string filePath = "data.txt";

if (File.Exists(filePath))
{
    string content = File.ReadAllText(filePath);
    Console.WriteLine("檔案內容:");
    Console.WriteLine(content);
}
else
{
    Console.WriteLine("找不到檔案!");
}

看到了嗎?對於簡單情況完全不用手動管理流!

3. 類別 Directory:管理資料夾不再痛苦

如果 File 處理單一檔案,那 Directory 就是處理資料夾(目錄)。

主要任務

方法 說明
Directory.Exists(path)
檢查資料夾是否存在
Directory.CreateDirectory(path)
建立資料夾(包含所有中間資料夾)
Directory.Delete(path)
刪除資料夾(可包含子目錄)
Directory.GetFiles(path)
取得資料夾中的檔案清單
Directory.GetDirectories(path)
取得子目錄清單
Directory.Move(source, destination)
移動或重新命名資料夾
Directory.GetCurrentDirectory()
取得應用程式的當前工作目錄

範例:建立資料夾並把檔案存進去

string dirPath = "Results";
if (!Directory.Exists(dirPath))
{
    Directory.CreateDirectory(dirPath);
    Console.WriteLine("資料夾 'Results' 已建立。");
}

string filePath = Path.Combine(dirPath, "summary.txt");
File.WriteAllText(filePath, "最終資料:...");

Console.WriteLine($"檔案 {filePath} 已寫入。");

4. FileDirectory 的典型使用情境

若只看到基本方法可能覺得無聊!我們用一個簡單的應用場景來展示它們的用法(假設我們做一個簡單的待辦清單系統 todo-list,結果儲存在檔案中)。

儲存資料到檔案(覆寫舊檔)

// 將待辦事項儲存到檔案
string[] todos = { "買麵包", "打電話給醫生", "做 C# 的作業" };
string filePath = "todo.txt";
File.WriteAllLines(filePath, todos);

Console.WriteLine("待辦清單已儲存。");

從檔案載入資料

// 若檔案存在則載入任務
if (File.Exists(filePath))
{
    string[] loadedTodos = File.ReadAllLines(filePath);
    Console.WriteLine("你的待辦清單:");
    foreach (var task in loadedTodos)
    {
        Console.WriteLine("- " + task);
    }
}
else
{
    Console.WriteLine("你還沒有待辦清單。");
}

新增任務(不覆寫檔案)

string newTask = "帶狗去散步";
File.AppendAllText(filePath, newTask + Environment.NewLine);
Console.WriteLine("任務已加入!");

複製與備份檔案

string backupPath = "todo_backup.txt";
File.Copy(filePath, backupPath, overwrite: true);
Console.WriteLine("待辦清單備份已建立。");

移動(或重新命名)檔案

string archivePath = "todo_archive.txt";
File.Move(filePath, archivePath);
Console.WriteLine("待辦清單已封存(重新命名)。");

刪除檔案

if (File.Exists(archivePath))
{
    File.Delete(archivePath);
    Console.WriteLine("封存已刪除 — 釋放空間!");
}

5. 資料夾操作:範例

建立目錄階層

string path = Path.Combine("Reports", "2024", "June");
Directory.CreateDirectory(path);
Console.WriteLine($"資料夾 {path} 已建立(包含中間資料夾)。");

取得檔案與資料夾清單

string dirPath = "Reports";
if (Directory.Exists(dirPath))
{
    string[] files = Directory.GetFiles(dirPath);
    Console.WriteLine("資料夾中的檔案:");
    foreach (var file in files)
    {
        Console.WriteLine(file);
    }

    string[] subDirs = Directory.GetDirectories(dirPath);
    Console.WriteLine("子目錄:");
    foreach (var dir in subDirs)
    {
        Console.WriteLine(dir);
    }
}

按遮罩過濾檔案(只要 .txt)

string[] txtFiles = Directory.GetFiles(dirPath, "*.txt");
Console.WriteLine("只有 .txt 檔案:");
foreach (var file in txtFiles)
{
    Console.WriteLine(file);
}

遞迴遍歷(所有子目錄中的檔案)

string[] allFiles = Directory.GetFiles(dirPath, "*.*", SearchOption.AllDirectories);
Console.WriteLine("所有子目錄中的檔案:");
foreach (var file in allFiles)
{
    Console.WriteLine(file);
}

移動與刪除目錄

string from = "OldReports";
string to = "Archive/OldReports";
if (Directory.Exists(from))
{
    Directory.Move(from, to);
    Console.WriteLine($"資料夾 {from} 已移動到 {to}");
}

if (Directory.Exists(to))
{
    Directory.Delete(to, recursive: true); // true: 刪除內部所有內容
    Console.WriteLine($"資料夾 {to} 已刪除(含所有內容)。");
}

6. 有用的小細節

與路徑整合:類別 Path

處理檔案與資料夾時常需要組合完整路徑、合併目錄與檔名、解析副檔名、檢查允許的字元。這些都可以用輔助類別 Path

範例

string folder = "Results";
string filename = "week1.txt";
string fullPath = Path.Combine(folder, filename); // 安全的合併方式!
Console.WriteLine(fullPath); // "Results/week1.txt"(或在 Windows 上是 "\")
  • 取得檔案副檔名: Path.GetExtension(fullPath)
  • 取得不含路徑的檔名: Path.GetFileName(fullPath)

Path.Combine 代替字串串接——對跨平台應用更安全。

「一次完成」的方法 vs 流式變體

很多 FileDirectory 的方法(例如 File.ReadAllText, File.WriteAllText, Directory.GetFiles)會把工作一次做完:讀取/寫入/取得檔案清單一次性完成。這非常方便,但不適合超大檔案或超大目錄,可能會耗盡記憶體。處理 GB 級資料時請改用流類別(StreamReader, StreamWriter, FileStream 等)或分段處理。

何時用 File/Directory,何時用流類別

情境 使用什麼
需要檢查檔案/資料夾是否存在
File.Exists, Directory.Exists
讀/寫整個小檔案
File.ReadAllText, WriteAllText
在檔案末尾加入文字
File.AppendAllText
取得目錄中的檔案清單
Directory.GetFiles
複製、刪除、移動檔案
File.Copy/Delete/Move
複製/刪除整個資料夾 Directory.Delete/Move/Copy(Copy 通常需第三方套件)
分段處理非常大的檔案 使用流類別(StreamReader, FileStream

實務意義與應用場景

  • 快速載入/儲存設定、設定檔、JSON/XML 檔案。
  • 記錄系統(將 log 寫到磁碟)。
  • 簡單的備份工具與資料遷移。
  • 掃描多媒體、照片、文件的資料夾。
  • 使用者情境:載入範本、匯出/匯入、產生報表等。

面試中的實作題也常會用到這些類別:例如「實作一個函式計算資料夾中所有 .txt 檔案的總大小」、「把檔案備份到另一個資料夾」等等。

視覺速查:什麼情況用哪個方法

graph TD
    A[你想做什麼?]
    A -->|檢查是否存在| B[File.Exists 或 Directory.Exists]
    A -->|整個讀/寫檔案| C[File.ReadAllText/WriteAllText]
    A -->|新增資料到檔案| D[File.AppendAllText]
    A -->|處理資料夾| E[Directory.CreateDirectory, GetFiles, GetDirectories]
    A -->|複製/刪除/移動檔案| F[File.Copy/Delete/Move]
    A -->|複製/刪除整個資料夾| G[Directory.Delete/Move]

7. 特性與常見錯誤

存在檢查與競態條件。即使先檢查了檔案/資料夾存在,另一個程序也可能在你實際操作前改變它。即便已檢查,還是要用 try-catch 包住實際操作!

存取權限。如果應用沒有讀/寫/刪除權限,方法會丟出 UnauthorizedAccessException

路徑太長。舊版 Windows 常見的最大路徑長度是 260 字元;在 .NET 9 情況有所改善,但仍要小心。

錯誤處理。像 File.ReadAllTextDirectory.GetFiles 這類方法遇到錯誤會直接丟例外:檔案/資料夾不存在就會失敗。把呼叫包在 try-catch 裡,或是先檢查存在性再操作。

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