C# 入門指南

單元 26 - 存檔與載入

~~學習進度表~~

存檔最簡單是將字串 (string) 儲存成文字檔案,因為字串最常用,所以 .NET 中有直接儲存字串為文字檔案的方式,這時候要加入以下的 using

下面看到存檔按鈕實作的 SaveButton_Click() 方法 (method)

以下為 SaveButton_Click() 的完整程式碼

private void SaveButton_Click(object sender, RoutedEventArgs e)
{
    string path = "code.text";
    using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
    {

        if (EncryptObject != null)
        {
            StreamWriter sw = new StreamWriter(fs, Encoding.Default);
            sw.WriteLine(EncryptObject.Code);
            sw.Close();
            DisplayBlock.Text = "存檔完成!";
        }
        else
        {
            DisplayBlock.Text = "沒有編碼物件!";
        }
    }
}

完整程式請參考「範例程式篇」的「 MainWindow.xaml.cs 」。

首先建立 path 變數, path 是存檔的檔案路徑,這裡只有放檔案名稱,因此 code.text 會在專案 (project) 的 📁bin 資料夾中。

string path = "code.text";

然後檢查 EncryptObject 是否為 null ,因為如果 EncryptObjectnull 就沒有 Code 屬性 (property) 可以儲存,注意到 using 這一行

using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))

這裡的 using 是建立 FileStream 型態的變數 fs ,也就是檔案物件,基本上會建立新的 code.text

此處 using 的作用與程式開頭引入程式庫 (library) 不同,這裡是讓 fs 的效力範圍只存在於底下大括弧的的空間,同時大括弧結束後自動釋放 fs 所佔據的記憶體空間。

下面當 EncryptObject 不是 null 就會啟動存檔程序

StreamWriter sw = new StreamWriter(fs, Encoding.Default);
sw.WriteLine(EncryptObject.Code);
sw.Close();
DisplayBlock.Text = "存檔完成!";

StreamWriter 型態的變數 sw 用來將文字內容寫入檔案,上面第 2 行用 WriteLine()Code 屬性,也就是密碼表寫入檔案中,第 3 行呼叫 Close() 方法關閉 StreamWriter 的物件 sw ,工作完成後就在 DisplayBlock 顯示「存檔完成!」

繼續看到 LoadButton_Click() 方法

以下為 LoadButton_Click() 的完整程式碼

private void LoadButton_Click(object sender, RoutedEventArgs e)
{
    string path = "code.text";
    if (File.Exists(path))
    {
        StreamReader sr = new StreamReader(path);
        EncryptObject = new Encrypt(sr.ReadLine());
        sr.Close();
        DisplayBlock.Text = "載入成功!";
    }
    else
    {
        DisplayBlock.Text = "載入失敗!";
    }
}

同樣建立檔案路徑變數 path

string path = "code.text";

然後利用 File 類別的 Exists() 方法,判斷檔案是否存在

if (File.Exists(path))

由於 Exists()static 方法,因此可以由類別名稱呼叫。

檔案存在才會進行載入工作

StreamReader sr = new StreamReader(path);
EncryptObject = new Encrypt(sr.ReadLine());
sr.Close();
DisplayBlock.Text = "載入成功!";

這裡換成用 StreamReader 型態的變數 sr ,並利用 ReadLine() 方法,讀取檔案的第一行,第一行也就是儲存密碼表的位置,然後把這一行的內容設定給新 Encrypt 型態的 EncryptObject 屬性。

重構版的 Encrypt 類別設計了可由參數建立密碼表 Code 屬性的建構子 (constructor) ,請參考單元 20 - 程式結構與重構

繼續按上方的開始按鈕進行測試,先按新建按鈕建立密碼表物件

然後按存檔按鈕

切換到專案的 📁bin 中的 📁Debug 資料夾,可以看到多了 code.txt

編譯好的 WpfAppDemo.exe 就是放在 📁bin 中的 📁Debug 資料夾。

打開 code.txt ,可以看到裡頭第一行就是儲存密碼表

回到「編密碼小工具」視窗,進行編碼測試

換成其他的密碼表編碼

重新載入

重新用已儲存的密碼表編碼

存檔載入,下一個單元繼續實作其他兩個拷貝清除按鈕。

相關教學影片

上一頁 單元 25 - 整合 Encrypt 類別
回 C# 入門指南首頁
下一頁 單元 27 - 完成版的 WpfAppDemo 專案
回 C# 教材首頁
回程式語言教材首頁
中英文術語對照
建構子constructor
程式庫library
方法method
專案project
屬性property
字串string
參考資料
1. Visual Studio | Microsoft Docs - 使用 Visual Studio 進行 C# 開發
2. Visual Studio | Microsoft Docs - 教學課程:使用 C# 建立一個簡單的應用程式
重點整理
1. 存檔按鈕是直接把密碼表儲存到純文字檔案中,載入按鈕就直接用密碼表設定 Encrypt 物件。
2. 關鍵字 using 可以設定變數的效力範圍只存在於特定的程式區塊。
問題與討論
1. 如果沒有 Encrypt 物件就進行存檔會怎麼樣呢?
2. 為什麼載入前要先檢查檔案存不存在?
練習
1. 承接上一個單元的 HelloDemo 專案,將 ClickMeContent 屬性設定為「已按」。
2. 承接上一個單元的 GuessGameDemo 專案,加入以下程式碼
// 引入計算核心
using GuessGame;
3. 承上題,在 GameWindow 類別中加入 Guess 型態的 Game 屬性。
4. 承上題,快速點擊新遊戲按鈕兩次,建立 NewGame_Click() 方法,然後在 NewGame_Click() 中加入以下程式碼
Display.Document.Blocks.Clear();
Game = new Guess(Number);
Display.AppendText("遊戲開始\r");
5. 承上題,若按執行鍵會發生 Program.cs 的錯誤,此時回到 Program.cs 加入以下程式碼
// 讓 string 可當 char
using System.Linq;
6. 承上題,快速點擊重選按鈕兩次,建立 Reset_Click() 方法,然後在 Reset_Click() 中加入以下程式碼
MainWindow main = new MainWindow();
main.Show();
Close();