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

C# 讀寫 INI 配置文件完整封裝:Win32 API 實戰與現代化用法指南

     編輯:關於C語言

前言

雖然 .NET 推薦使用 app.config / appsettings.json,但在輕量工具、舊專案遷移、跨語言共享配置等場景下,INI 以其純文本、結構簡單、無依賴的特性仍具備不可替代的優勢。本文封裝一個開箱即用的 IniFile 類,底層調用 kernel32.dll 的 WritePrivateProfileString / GetPrivateProfileString,支援 Section/Key 結構、預設 Section、存在性檢查,並提供現代化調用範例。

INI 文件結構速覽

[SectionName]
Key1=Value1
Key2=Value2

[AnotherSection]
IP=127.0.0.1
Port=8080
  • Section:以 [ ] 包裹,分組用途。
  • Key=Value:屬於最近一個 Section,值為字串。
  • 註解以 ; 或 # 開頭(WinAPI 會自動忽略)。

核心封裝:IniFile.cs

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

public class IniFile
{
    public string Path { get; }

    [DllImport("kernel32", CharSet = CharSet.Unicode)]
    private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);

    [DllImport("kernel32", CharSet = CharSet.Unicode)]
    private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

    /// 
    /// 建構函式,預設當前目錄下 default.ini
    /// 
    public IniFile(string iniPath = ".\\default.ini") => Path = Path.GetFullPath(iniPath);

    /// 寫入指定 Section/Key
    public void Write(string section, string key, string value) =>
        WritePrivateProfileString(section, key, value, Path);

    /// 寫入預設 Section (default)
    public void Write(string key, string value) =>
        WritePrivateProfileString("default", key, value, Path);

    /// 讀取指定 Section/Key,不存在回傳空字串
    public string Read(string section, string key)
    {
        var sb = new StringBuilder(256);
        GetPrivateProfileString(section, key, "", sb, 256, Path);
        return sb.ToString();
    }

    /// 讀取預設 Section (default)
    public string Read(string key) => Read("default", key);

    /// 檢查文件是否存在
    public bool Exists() => File.Exists(Path);
}

現代化用法範例

class Program
{
    static void Main()
    {
        // 1. 實例化(支援相對/絕對路徑)
        var ini = new IniFile(@".\config\app.ini");

        // 2. 寫入配置
        ini.Write("Database", "Host", "127.0.0.1");
        ini.Write("Database", "Port", "3306");
        ini.Write("Database", "User", "root");
        ini.Write("Database", "Pwd", "secret");

        ini.Write("App", "Version", "1.2.3");
        ini.Write("App", "AutoUpdate", "true");

        // 3. 讀取配置(強型別轉換自行處理)
        string host = ini.Read("Database", "Host");
        int port = int.Parse(ini.Read("Database", "Port"));
        bool autoUpdate = bool.Parse(ini.Read("App", "AutoUpdate"));

        Console.WriteLine($"連線 {host}:{port} | 自動更新:{autoUpdate}");

        // 4. 預設 Section 簡寫
        ini.Write("LastLogin", "user001");        // 寫入 [default] LastLogin=user001
        string last = ini.Read("LastLogin");      // 讀取 [default] LastLogin

        // 5. 檢查文件存在
        if (!ini.Exists()) Console.WriteLine("配置文件遺失,將建立預設值。");

        Console.ReadKey();
    }
}

進階議題與最佳實踐

1. 緩衝區大小與長值支援

預設 StringBuilder(256) 足夠大多數場景。若值可能超過 255 字元,請擴大容量並傳入 size 參數;WinAPI 會在緩衝區不足時截斷,不會拋出異常。

2. 字元編碼與 Unicode

CharSet = CharSet.Unicode 確保中文、特殊字元正確讀寫。若需相容 ANSI 版本(極舊系統),可改 CharSet.Ansi 並儲存為 ANSI 編碼檔案。

3. 執行緒安全

WinAPI 函式本身是執行緒安全的,但同一進程多執行緒高頻寫入同一檔案可能導致內容交錯。建議在上層加 lock 或使用單例模式集中管理。

4. 效能考量

每次讀寫皆觸發磁碟 I/O。頻繁操作時,建議:

  • 啟動時一次性 Read 所有鍵值快取到記憶體 Dictionary。
  • 運行期僅操作記憶體,關機或定時 Write 回檔。

5. 替代方案對比

方案優點缺點適用場景
INI + WinAPI零依賴、跨語言、人類可讀無型別、無巢狀、頻繁 I/O 慢輕量工具、啟動參數、跨進程共享
XML / JSON結構豐富、生態完善需序列化庫、檔案較大現代 .NET 應用標配
Registry系統級、權限隔離寫入需管理員、難備份遷移系統級設定、文件關聯

總結

IniFile 類以 50 行核心代碼封裝了 Win32 API 的讀寫細節,提供直觀的 Write/Read 介面,開箱即用。若專案僅需簡單配置持久化,它是比引入 JSON 庫更輕量的選擇;若配置結構複雜、需型別安全,請毫猶豫遷移至 System.Text.Json + appsettings.json。選對工具,才能事半功倍。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved