iT邦幫忙

2025 iThome 鐵人賽

DAY 23
0
佛心分享-IT 人自學之術

30 天從 Python 轉職場 C# 新手入門系列 第 23

Day23-C#檔案存取(File and Stream I/O)

  • 分享至 

  • xImage
  •  

前言

前兩天我們學了非同步程式設計(async / await),今天要來看看實務上非常常見的一個應用場景──檔案存取 (File I/O)。不論是紀錄日誌、讀取設定檔,還是匯入匯出資料,都會需要操作檔案。C# 提供了許多方便的類別,像 File, FileInfo, StreamReader, StreamWriter 等等,可以快速完成這些任務。而且這些操作也能配合非同步寫法 (File.ReadAllTextAsync, File.WriteAllTextAsync),讓程式在讀寫大型檔案時不會卡住 UI 或主執行緒。


檔案與資料流 I/O(File and Stream I/O)

檔案與資料流輸入/輸出(I/O, Input/Output)指的是資料在儲存媒介之間的傳輸。在 .NET 中,System.IO 命名空間包含了可用來同步與非同步地讀取與寫入資料流與檔案的型別。這些命名空間也提供了用於壓縮與解壓縮檔案的型別,以及可透過 管道(pipes)與序列埠(serial ports) 進行通訊的型別。


檔案(Files)與目錄(Directories)

檔案是一個有順序且具名稱的位元組集合,並具有持久性的儲存空間,當你處理檔案時,會涉及目錄路徑、磁碟儲存以及檔案與目錄名稱。相較之下, 資料流(stream) 是一連串的位元組,可用來從後端儲存體讀取或寫入資料,而這個後端儲存體可能是磁碟、記憶體或其他媒介。不僅僅有檔案資料流,也有網路資料流、記憶體資料流與管道資料流等其他種類。可以使用 System.IO 命名空間中的類別與檔案或目錄互動,例如:

  • 取得與設定檔案或目錄的屬性。
  • 根據搜尋條件擷取檔案與目錄集合。

常用的檔案與目錄類別如下:

類別 說明
File 提供建立、複製、刪除、移動與開啟檔案的靜態方法,並可建立 FileStream 物件。
FileInfo 提供上述動作的執行個體方法。
Directory 提供建立、移動及列舉目錄與子目錄的靜態方法。
DirectoryInfo 提供上述動作的執行個體方法。
Path 提供跨平台處理目錄字串的方法與屬性。

資料流(Streams)

抽象基底類別 Stream 支援讀取與寫入位元組,所有表示資料流的類別都繼承自 Stream。Stream 類別及其衍生類別提供對資料來源與儲存體的共同介面,讓開發者不需關心作業系統或底層裝置的細節。
資料流的三個基本操作為:

  1. 讀取(Reading):將資料從資料流轉入資料結構(例如位元組陣列)。
  2. 寫入(Writing):將資料從來源輸出到資料流。
  3. 定位(Seeking):查詢與修改資料流中的目前位置。

不同資料來源可能支援不同的功能,例如 PipeStream 不支援定位操作。可使用屬性 CanRead、CanWrite、CanSeek 來檢查資料流是否支援特定操作。

常用的資料流類別如下:

類別 功能
FileStream 用於讀寫檔案。
IsolatedStorageFileStream 用於隔離儲存區中的檔案。
MemoryStream 用於記憶體中讀寫資料。
BufferedStream 改善讀寫效能。
NetworkStream 用於網路通訊的資料流。
PipeStream 用於匿名或具名管道的資料流。
CryptoStream 將資料流連結至加密/解密轉換。

讀取器與寫入器(Readers and Writers)

System.IO 命名空間也提供了處理文字編碼字元的讀寫類別。資料流通常以位元組為單位進行 I/O,而讀取器與寫入器會在位元組與字元之間進行轉換。每個讀寫類別都關聯至一個資料流,可透過 BaseStream 屬性取得。

常用的讀寫類別如下:

類別 功能
BinaryReader / BinaryWriter 以二進位格式讀寫基本資料型別。
StreamReader / StreamWriter 使用指定編碼讀寫文字。
StringReader / StringWriter 從字串中讀取或寫入字元。
TextReader / TextWriter 為所有文字讀寫器的抽象基底類別。

非同步 I/O 操作(Asynchronous I/O Operations)

在處理大量資料時,應使用非同步操作以避免 UI 卡頓,同步 I/O 會阻塞 UI 執行緒直到操作完成,而非同步 I/O 可讓應用程式保持回應。非同步成員的名稱中通常包含 Async,例如:

  • CopyToAsync
  • FlushAsync
  • ReadAsync
  • WriteAsync

這些方法可搭配 async 與 await 關鍵字使用。


壓縮與解壓縮(Compression)

壓縮是將檔案大小縮小以便儲存;解壓縮則是還原成可使用的格式。System.IO.Compression 命名空間包含壓縮與解壓縮檔案與資料流的型別。

常用類別如下:

類別 功能
ZipArchive 建立與存取 zip 壓縮檔案中的項目。
ZipArchiveEntry 代表壓縮檔中的單一檔案。
ZipFile 建立、解壓與開啟壓縮檔。
ZipFileExtensions 針對壓縮封裝建立或提取項目。
DeflateStream 使用 Deflate 演算法進行壓縮/解壓。
GZipStream 使用 gzip 格式進行壓縮/解壓。

隔離儲存(Isolated Storage)

隔離儲存是一種具安全性與隔離性的儲存機制,透過使用者、組件(assembly)與網域來分隔資料。這對於應用程式無法直接存取使用者檔案的情況特別有用,例如儲存設定檔或暫存資料。隔離儲存在 Windows 8.x 應用程式中不可用,請改用 Windows.Storage 命名空間中的應用程式資料類別。常用類別如下:

  • IsolatedStorage – 隔離儲存實作的基底類別。
  • IsolatedStorageFile – 提供隔離儲存空間。
  • IsolatedStorageFileStream – 用於存取隔離儲存區中的檔案。

程式範例

  1. 基本範例:寫入與讀取文字檔
using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        string filePath = "example.txt";
        string content = "Hello, IT 鐵人賽!這是我的第 20 天學習紀錄。";

        // 非同步寫入
        await File.WriteAllTextAsync(filePath, content);
        Console.WriteLine("✅ 寫入完成!");

        // 非同步讀取
        string result = await File.ReadAllTextAsync(filePath);
        Console.WriteLine("📄 檔案內容:");
        Console.WriteLine(result);
    }
}

執行結果:
✅ 寫入完成!
📄 檔案內容:
Hello, IT 鐵人賽!這是我的第 20 天學習紀錄。
https://ithelp.ithome.com.tw/upload/images/20251005/20178767CVKsjneu8F.png
可以看到在目錄多了一個example.txt的檔案,並且把Hello, IT 鐵人賽!這是我的第 20 天學習紀錄。寫進檔案內。
2. 進階範例:逐行寫入與讀取 (StreamWriter / StreamReader)
有時候我們不想一次載入整個檔案,而是想一行一行處理:

using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        string path = "log.txt";

        // 寫入多行文字
        using (StreamWriter writer = new StreamWriter(path))
        {
            for (int i = 1; i <= 3; i++)
            {
                await writer.WriteLineAsync($"第 {i} 行:紀錄時間 {DateTime.Now}");
            }
        }

        // 讀取多行文字
        using (StreamReader reader = new StreamReader(path))
        {
            string? line;
            while ((line = await reader.ReadLineAsync()) != null)
            {
                Console.WriteLine(line);
            }
        }
    }
}

執行結果:
第 1 行:紀錄時間 10/5/2025 9:46:36 PM
第 2 行:紀錄時間 10/5/2025 9:46:36 PM
第 3 行:紀錄時間 10/5/2025 9:46:36 PM

而一樣可以在目錄看到log.txt檔。


上一篇
Day22-C#非同步編程續集
系列文
30 天從 Python 轉職場 C# 新手入門23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言