C# WinForm INI文件读写+INI文件高阶读写(完整工具类)

INI配置文件基础读写

一、INI文件核心基础概念

1. 什么是INI配置文件

INI 是 Windows 系统原生的轻量级配置文件,专门用来存储软件固定配置:服务器地址、端口、账号、参数设置等。

特点:纯文本、结构简单、无需第三方组件、开机常驻系统支持、读写稳定。

2. INI固定语法结构(必考)

复制代码
[节点(Section)]
键名(Key)=值(Value)

层级关系:文件 → 节点(节) → 键 → 值

示例:

复制代码
[Address]
serve=127.0.0.1
port=8080

3. 读写原理

C# 没有原生INI读写类,必须调用 Windows 系统内核动态链接库:kernel32.dll

通过 DllImport 导入系统原生API,再进行二次封装,方便项目调用。

二、项目前置必备配置(不配置代码直接报错)

1. 程序集引用

右键项目 → 添加引用 → 程序集 → 勾选:System.Configuration

2. 必须引入的命名空间

复制代码
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text;
using System.Configuration;

三、App.config 配置文件详解(独立模块)

作用:统一管理INI文件路径,避免代码写死路径,方便后期修改路径。

复制代码
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
    </startup>

	<!-- 自定义配置节点 -->
	<appSettings>
		<!-- key:配置名  value:INI文件绝对路径 -->
		<add key="filePath" value="C:\Users\Administrator\Desktop\第29天\2 ini文件读写\bin\Debug\1.txt"/>
	</appSettings>
</configuration>

解析:程序通过 ConfigurationManager 读取 filePath 对应的路径,实现路径统一配置。


四、INI工具类 INITool 逐段拆解讲解

1. 命名空间与全局路径读取

复制代码
namespace _2_ini文件读写
{
    public class INITool
    {
        //读取App.config中配置的INI文件路径
        //必须引用 System.Configuration 否则报错
        private static string filePath = ConfigurationManager.AppSettings["filePath"].ToString();

作用:全局静态路径,所有读写方法统一使用该路径,无需重复写路径。

2. 内核DLL写入API声明

复制代码
        //引入Windows系统内核dll
        //SetLastError=true 开启错误码捕获
        [DllImport("kernel32.dll",CharSet = CharSet.Auto,SetLastError = true)]
        [return:MarshalAs(UnmanagedType.Bool)]
        //原生API:写入INI键值对
        public static extern bool WritePrivateProfileString(
            string lpAppName,    //节点名称(节名)
            string lpKeyName,    //键名
            string lpString,     //需要写入的值
            string lpFileName    //ini文件路径
        );

细节说明:

CharSet.Auto:自动适配系统编码,避免中文乱码

SetLastError:开启系统错误捕获,方便排错

MarshalAs:指定非托管返回值类型

3. 内核DLL读取API声明

复制代码
        //原生API:读取INI指定键值
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileString(
            string lpAppName,              //节点名
            string lpKeyName,              //键名
            string lpDefault,              //读取失败默认值
            StringBuilder lpReturnedString, //接收读取结果的缓冲区
            uint nSize,                    //缓冲区大小
            string lpFileName              //文件路径
        );

4. 封装写入方法(对外调用)

对原生复杂API进行二次封装,简化调用参数

复制代码
        /// <summary>
        /// INI写入方法
        /// </summary>
        /// <param name="section">节点名称</param>
        /// <param name="key">键名称</param>
        /// <param name="value">写入的值</param>
        public static void Write(string section,string key,string value)
        {
            //调用系统原生写入方法
            WritePrivateProfileString(section,key,value, filePath);
        }

调用规则:

  1. 节点不存在 → 自动创建节点

  2. 键不存在 → 新增键值对

  3. 键已存在 → 覆盖原值

5. 封装读取方法(对外调用)

复制代码
        /// <summary>
        /// INI读取方法
        /// </summary>
        /// <param name="section">节点名</param>
        /// <param name="key">键名</param>
        /// <returns>返回读取到的值</returns>
        public static string Read(string section, string key)
        {
            //创建字符串缓冲区,接收读取数据
            StringBuilder sb = new StringBuilder();
            //读取数据,默认值为空,缓冲区大小255
            GetPrivateProfileString(section, key,"",sb,255,filePath);
            //返回读取到的字符串
            return sb.ToString();
        }

    }
}

细节:缓冲区大小255,足够存储普通配置文本,读取不到内容返回空字符串。


五、窗体Form1 代码逐段拆解

1. 窗体全局路径定义

复制代码
namespace _2_ini文件读写
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //全局读取配置文件路径,与工具类路径保持一致
        private static string filePath = ConfigurationManager.AppSettings["filePath"].ToString();

2. 写入按钮功能(Button1)

功能:将文本框内容写入INI文件的Address节点下

复制代码
        //写入INI配置
        private void button1_Click(object sender, EventArgs e)
        {
            //写入节点Address下的 serve 键
            INITool.Write("Address","serve",textBox1.Text);
            //写入节点Address下的 port 键
            INITool.Write("Address", "port", textBox2.Text);
        }

执行后INI文件效果:

复制代码
[Address]
serve=用户输入内容
port=用户输入内容

3. 读取按钮功能(Button2)

功能:读取INI指定节点、指定键的值,赋值给文本框展示

复制代码
        //读取INI配置
        private void button2_Click(object sender, EventArgs e)
        {
            //读取serve的值显示到文本框1
            textBox1.Text = INITool.Read("Address","serve");
            //读取port的值显示到文本框2
            textBox2.Text = INITool.Read("Address", "port");
        }
    }
}

六、完整执行流程

1、在App.config配置INI文件路径

2、程序启动读取配置路径

3、点击写入:调用封装Write方法 → 调用内核API → 写入/覆盖INI键值

4、点击读取:调用封装Read方法 → 读取内核缓冲区数据 → 展示到文本框

七、核心知识点总结

1、INI结构:节点 键=值

2、读写依赖:kernel32.dll 系统API

3、DllImport:托管代码调用非托管系统方法

4、二次封装意义:屏蔽复杂参数,调用极简、易维护

5、配置文件优势:路径统一管理,无需改代码改路径

八、易错点超级总结

1、未添加 System.Configuration 引用 → 读取配置报错

2、路径写错 → 文件找不到,读写无效果

3、节点名、键名大小写不一致 → 读取不到数据

4、未使用StringBuilder缓冲区 → 无法接收读取数据

5、重复写入同名键 → 自动覆盖旧数据

C# WinForm INI文件读写(第二种笔记)

一、项目功能概述

本项目基于 C# WinForm + Windows kernel32.dll API 实现标准 INI 配置文件的读写功能。

核心功能:

  • 1、将文本框输入的服务器地址、端口写入本地INI配置文件

  • 2、读取INI文件中指定节点、键名的配置数据,回显到界面文本框

  • 3、通过App.config统一管理INI文件路径,实现配置解耦

INI文件标准格式:节点名 键=值,适合存储轻量级程序配置。

二、项目前置环境配置(必看,否则报错)

2.1 项目引用添加

右键项目 → 添加 → 引用,必须引入两个程序集:

  • System.Configuration:用于读取App.config配置文件参数

  • System.Runtime.InteropServices:用于DllImport调用系统外部API

2.2 命名空间引用

代码顶部必须引入以下命名空间,否则关键字无法识别

复制代码
using System;
using System.Configuration;      //读取配置文件
using System.Runtime.InteropServices;  //调用系统dll
using System.Text;             //字符串缓冲区
using System.Windows.Forms;

三、App.config 配置文件完整解析

3.1 完整源码

复制代码
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
    </startup>

	<appSettings>
		<add key="filePath" value="C:\Users\Administrator\Desktop\第29天\2 ini文件读写\bin\Debug\1.txt"/>
	</appSettings>
</configuration>

3.2 逐段解析

  • supportedRuntime:指定程序运行的.NET框架版本,当前为.NET4.8

  • appSettings:自定义配置节点,专门存放自定义键值对

  • key="filePath":自定义键名,用于代码中读取INI文件路径

  • value:INI配置文件的绝对物理路径,程序所有读写操作都针对该文件

作用:将文件路径写在配置文件中,不硬编码在代码里,后续修改路径无需改代码,直接改配置文件即可。

四、核心工具类 INITool 逐行详解

INITool 是自定义封装的INI操作工具类,核心原理:调用Windows系统内核 kernel32.dll 原生API实现读写

4.1 定义命名空间与全局路径

复制代码
namespace _2_ini文件读写
{
    public class INITool
    {
        //读取app.config中配置的INI文件路径
        private static string filePath = ConfigurationManager.AppSettings["filePath"].ToString();
}

代码解析

  • ConfigurationManager.AppSettings["filePath"]:读取App.config中appSettings节点下key为filePath的值

  • 静态字段:全局唯一,整个工具类共享同一个文件路径

  • 解决硬编码问题,统一管理文件路径

4.2 kernel32.dll 原理说明

kernel32.dll 是Windows系统核心内核动态链接库,系统自带,无需手动引入,负责内存管理、文件IO、系统交互。

C# 本身没有原生INI读写方法,只能通过 DllImport 跨语言调用 系统原生API实现功能。

4.3 写入API声明(核心)

复制代码
[DllImport("kernel32.dll",CharSet = CharSet.Auto,SetLastError = true)]
[return:MarshalAs(UnmanagedType.Bool)]
public static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);

特性标签解析

  • DllImport("kernel32.dll"):声明调用系统内核dll中的外部方法

  • CharSet = CharSet.Auto:自动适配系统字符集,兼容中文不乱码

  • SetLastError = true:开启系统错误捕获,可获取API调用失败错误码

  • MarshalAs(UnmanagedType.Bool):将C++原生布尔类型转换为C#可识别的bool类型

方法参数详解

  • lpAppName:INI文件的节点名(例如 Address

  • lpKeyName:节点下的键名(serve、port)

  • lpString:需要写入的键值

  • lpFileName:INI文件的完整物理路径

4.4 读取API声明(核心)

复制代码
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, uint nSize, string lpFileName);

参数详解

  • lpAppName:INI节点名

  • lpKeyName:需要读取的键名

  • lpDefault:读取失败时的默认值(此处为空)

  • lpReturnedString:字符串缓冲区,接收读取到的值

  • nSize:缓冲区最大容量(限制读取字符长度)

  • lpFileName:文件路径

4.5 自定义封装Write写入方法

复制代码
/// <summary>
///  写入ini
/// </summary&gt;
/// &lt;param name="section"> 节名称</param>
/// <param name="key"> 键名称</param>
/// &lt;param name="value"> 值</param>
public static void Write(string section,string key,string value)
{
    WritePrivateProfileString(section,key,value, filePath);
}

封装意义

  • 原生API参数多、使用复杂,封装后简化调用

  • 外部窗体只需传 节点、键、值 三个参数即可完成写入

  • 统一复用文件路径,无需重复传参

4.6 自定义封装Read读取方法

复制代码
/// <summary>
/// 读取指定节 键的值
/// </summary>
/// <param name="section"></param>
/// &lt;param name="key"></param>
/// <returns></returns>
public static string Read(string section, string key)
{
    StringBuilder sb = new StringBuilder();
    GetPrivateProfileString(section, key,"",sb,255,filePath);
    return sb.ToString();
}

代码解析

  • StringBuilder sb:创建字符串缓冲区,接收读取结果

  • 默认值为空字符串,读取不到数据返回空

  • 缓冲区大小255,支持短文本配置存储

  • 最后将缓冲区内容转为字符串返回给调用处

五、窗体Form1 业务代码逐段详解

5.1 窗体构造方法

复制代码
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

作用:初始化窗体所有控件(文本框、按钮等),WinForm程序固定写法。

5.2 写入按钮点击事件(button1)

复制代码
//写入
private void button1_Click(object sender, EventArgs e)
{
    INITool.Write("Address","serve",textBox1.Text);
    INITool.Write("Address", "port", textBox2.Text);
}

业务逻辑

  • 调用封装好的工具类写入方法

  • 在INI文件中创建/覆盖 [Address] 节点

  • 将textBox1内容写入 serve 键

  • 将textBox2内容写入 port 键

写入后INI文件效果

复制代码
[Address]
serve=输入的服务器地址
port=输入的端口号

5.3 读取按钮点击事件(button2)

复制代码
//读取
private void button2_Click(object sender, EventArgs e)
{
    textBox1.Text =   INITool.Read("Address","serve");
    textBox2.Text = INITool.Read("Address", "port");
}

业务逻辑

  • 读取INI文件Address节点下的serve值,赋值给第一个文本框

  • 读取INI文件Address节点下的port值,赋值给第二个文本框

  • 实现配置数据回显

六、原代码BUG问题总结(重点避坑)

  • BUG1:重复定义 filePath:窗体类和工具类重复声明静态路径字段,编译报错

  • BUG2:重复嵌套命名空间:代码拼接导致命名空间重复包裹,语法不规范

  • BUG3:无容错处理:配置路径为空、文件不存在时,程序直接崩溃

  • BUG4:缓冲区过小:默认255字符,过长配置会被截断

七、整体运行流程总结

  1. 程序启动,工具类读取App.config中的INI文件路径

  2. 点击写入按钮:获取文本框内容 → 调用系统API → 写入本地INI文件

  3. 点击读取按钮:调用系统API读取文件内容 → 赋值到界面文本框

  4. 全程基于系统原生API,读写稳定、兼容性强,适合桌面程序配置存储

八、拓展优化方向

  • 1、将绝对路径改为相对路径,适配任意电脑运行

  • 2、增加文件不存在自动创建逻辑,避免报错

  • 3、增加空值判断,防止写入空配置

  • 4、扩容字符串缓冲区,支持长文本配置

INI文件高阶读写(完整工具类)了解

一、知识点前置

1、INI文件结构:节点(Section) 键(Key)=值(Value)

2、C#无原生INI操作,依赖 kernel32.dll Windows系统API

3、特点:节点、键名不区分大小写;文件不存在自动创建

4、必备引用:System.Configuration、System.Runtime.InteropServices、System.Text

二、整体结构划分

1、原生API声明(底层系统方法)

2、二次封装工具方法(开发直接调用)

3、窗体调用演示(增、删、改、查、批量读取)


三、底层 Kernel32 API 声明代码

作用:导入系统原生INI读写函数,为上层封装提供底层支撑

复制代码
namespace Tool
{
    public class IniAPI
    {
        #region 底层API声明

        /// <summary>
        /// 获取INI所有节点名称
        /// </summary>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer, uint nSize, string lpFileName);

        /// <summary>
        /// 获取指定节点下所有键值对
        /// </summary>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileSection(string lpAppName, IntPtr lpReturnedString, uint nSize, string lpFileName);

        /// <summary>
        /// 读取字符串(char数组缓冲区)
        /// </summary>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, [In, Out] char[] lpReturnedString, uint nSize, string lpFileName);

        /// <summary>
        /// 读取字符串(StringBuilder缓冲区)
        /// </summary>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, uint nSize, string lpFileName);

        /// <summary>
        /// 读取字符串(string缓冲区)
        /// </summary>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, string lpReturnedString, uint nSize, string lpFileName);

        /// <summary>
        /// 写入/覆盖节点整体内容
        /// </summary>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool WritePrivateProfileSection(string lpAppName, string lpString, string lpFileName);

        /// <summary>
        /// 写入/覆盖单个键值对
        /// </summary>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);

        #endregion

四、高阶封装:查询系列方法

1、获取INI所有节点名称

复制代码
/// <summary>
/// 获取所有Section节点
/// </summary>
public static string[] INIGetAllSectionNames(string iniFile)
{
    uint MAX_BUFFER = 32767;
    string[] sections = new string[0];

    //分配非托管内存
    IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));
    uint bytesReturned = IniAPI.GetPrivateProfileSectionNames(pReturnedString, MAX_BUFFER, iniFile);

    if (bytesReturned != 0)
    {
        //解析内存字符串,以\0切割
        string local = Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned);
        sections = local.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
    }

    //释放内存,防止内存泄漏
    Marshal.FreeCoTaskMem(pReturnedString);
    return sections;
}

2、获取指定节点所有键值对(key=value)

复制代码
/// <summary>
/// 获取指定节点下所有键值对
/// </summary>
public static string[] INIGetAllItems(string iniFile, string section)
{
    uint MAX_BUFFER = 32767;
    string[] items = new string[0];

    IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));
    uint bytesReturned = IniAPI.GetPrivateProfileSection(section, pReturnedString, MAX_BUFFER, iniFile);

    if (!(bytesReturned == MAX_BUFFER - 2) || (bytesReturned == 0))
    {
        string returnedString = Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned);
        items = returnedString.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
    }

    Marshal.FreeCoTaskMem(pReturnedString);
    return items;
}

3、获取指定节点所有Key键名

复制代码
/// <summary>
/// 获取节点下所有键名
/// </summary>
public static string[] INIGetAllItemKeys(string iniFile, string section)
{
    string[] value = new string[0];
    const int SIZE = 1024 * 10;

    if (string.IsNullOrEmpty(section))
        throw new ArgumentException("必须指定节点名称", "section");

    char[] chars = new char[SIZE];
    uint bytesReturned = IniAPI.GetPrivateProfileString(section, null, null, chars, SIZE, iniFile);

    if (bytesReturned != 0)
    {
        value = new string(chars).Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
    }
    chars = null;
    return value;
}

4、读取字符串值(带默认值)

复制代码
/// <summary>
/// 读取字符串配置,找不到返回默认值
/// </summary>
public static string INIGetStringValue(string iniFile, string section, string key, string defaultValue)
{
    string value = defaultValue;
    const int SIZE = 1024 * 10;

    if (string.IsNullOrEmpty(section))
        throw new ArgumentException("必须指定节点名称", "section");
    if (string.IsNullOrEmpty(key))
        throw new ArgumentException("必须指定键名称(key)", "key");

    StringBuilder sb = new StringBuilder(SIZE);
    uint bytesReturned = IniAPI.GetPrivateProfileString(section, key, defaultValue, sb, SIZE, iniFile);

    if (bytesReturned != 0)
        value = sb.ToString();

    sb = null;
    return value;
}

5、扩展读取:int、double、string 快捷方法

复制代码
//读取int类型
public static int GetPrivateProfileInt(string lpAppName, string lpKeyName, int Default, string lpFileName)
{
    StringBuilder lpReturnedString = new StringBuilder(1024);
    GetPrivateProfileString(lpAppName, lpKeyName, Convert.ToString(Default), lpReturnedString, 1024, lpFileName);
    return Convert.ToInt32(lpReturnedString.ToString());
}

//读取double浮点类型
public static double GetPrivateProfileDouble(string lpAppName, string lpKeyName, double Default, string lpFielName)
{
    StringBuilder lpReturnedString = new StringBuilder(1024);
    GetPrivateProfileString(lpAppName, lpKeyName, Convert.ToString(Default), lpReturnedString, 1024, lpFielName);
    return Convert.ToDouble(lpReturnedString.ToString());
}

//简易读取字符串
public static string GetPrivateProfileString(string lpAppName, string lpKeyName, string Default, string lpFileName)
{
    StringBuilder lpReturnedString = new StringBuilder(1024);
    GetPrivateProfileString(lpAppName, lpKeyName, Default, lpReturnedString, 1024, lpFileName);
    return lpReturnedString.ToString();
}

五、高阶封装:写入、删除系列方法

1、批量写入节点键值对

复制代码
public static bool INIWriteItems(string iniFile, string section, string items)
{
    if (string.IsNullOrEmpty(section))
        throw new ArgumentException("必须指定节点名称", "section");
    if (string.IsNullOrEmpty(items))
        throw new ArgumentException("必须指定键值对", "items");

    return IniAPI.WritePrivateProfileSection(section, items, iniFile);
}

2、单键值写入/覆盖

复制代码
public static bool INIWriteValue(string iniFile, string section, string key, string value)
{
    if (string.IsNullOrEmpty(section))
        throw new ArgumentException("必须指定节点名称", "section");
    if (string.IsNullOrEmpty(key))
        throw new ArgumentException("必须指定键名称", "key");
    if (value == null)
        throw new ArgumentException("值不能为null", "value");

    return IniAPI.WritePrivateProfileString(section, key, value, iniFile);
}

3、删除单个Key

复制代码
public static bool INIDeleteKey(string iniFile, string section, string key)
{
    if (string.IsNullOrEmpty(section))
        throw new ArgumentException("必须指定节点名称", "section");
    if (string.IsNullOrEmpty(key))
        throw new ArgumentException("必须指定键名称", "key");

    //value传null = 删除该键
    return IniAPI.WritePrivateProfileString(section, key, null, iniFile);
}

4、删除整个节点

复制代码
public static bool INIDeleteSection(string iniFile, string section)
{
    if (string.IsNullOrEmpty(section))
        throw new ArgumentException("必须指定节点名称", "section");

    //key、value都传null = 删除整个节点
    return IniAPI.WritePrivateProfileString(section, null, null, iniFile);
}

5、清空节点所有内容(保留节点)

复制代码
public static bool INIEmptySection(string iniFile, string section)
{
    if (string.IsNullOrEmpty(section))
        throw new ArgumentException("必须指定节点名称", "section");

    //内容传空字符串 = 清空节点数据
    return IniAPI.WritePrivateProfileSection(section, string.Empty, iniFile);
}

#endregion
#endregion
    }
}

六、窗体调用完整代码(实战演示)

1、读取配置文件路径

复制代码
//读取App.config中配置的INI文件路径
private static string filePath = ConfigurationManager.AppSettings["filePath"].ToString();

2、批量读取节点所有键值对(Button3)

功能:读取 Address 节点下所有 key=value 数据并弹窗展示

复制代码
private void button3_Click(object sender, EventArgs e)
{
    //获取指定节点所有键值对数组
    string[] arr = IniAPI.INIGetAllItems(filePath, "Address");
    foreach (string item in arr)
    {
        MessageBox.Show(item);
    }
}

3、新增/写入自定义节点键值(Button4)

功能:创建【相机】节点,写入曝光参数,存在则覆盖

复制代码
private void button4_Click(object sender, EventArgs e)
{
    //写入:节点=相机,键=曝光,值=300
    IniAPI.INIWriteValue(filePath,"相机","曝光","300");
}

4、读取指定键值 + 默认值容错(Button5)

功能:读取端口值,读取失败返回默认值ss,赋值给窗体标题

复制代码
private void button5_Click(object sender, EventArgs e)
{
    //参数:路径、节点、键、默认值
    this.Text = IniAPI.INIGetStringValue(filePath,"Address","port","ss");

    //扩展:删除指定键
    //IniAPI.INIDeleteKey(filePath,"Address","port");
}

七、INI工具类全部功能汇总(必背)

查询功能

1、INIGetAllSectionNames:获取全部节点

2、INIGetAllItems:获取节点全部键值对

3、INIGetAllItemKeys:获取节点全部键名

4、INIGetStringValue:读取字符串(带默认值)

5、GetPrivateProfileInt:读取整型

6、GetPrivateProfileDouble:读取浮点型

写入功能

1、INIWriteValue:单条键值写入/覆盖

2、INIWriteItems:批量写入节点数据

删除功能

1、INIDeleteKey:删除单个键

2、INIEmptySection:清空节点内容,保留节点

3、INIDeleteSection:删除整个节点

八、核心底层原理细节(必考)

1、CharSet.Auto:自动适配系统编码,读取必须搭配 Marshal.PtrToStringAuto

2、StringBuilder 无法识别 \0 截断字符,只能用于单键值读取

3、IntPtr 非托管内存,使用后必须 FreeCoTaskMem 释放,防止内存泄漏

4、写入传 null / 空字符串 具备不同删除逻辑

5、INI文件不存在时,API会自动创建空文件

九、易错点总结

1、未添加 System.Configuration 引用,读取App配置报错

2、非托管内存不释放,造成内存泄漏

3、节点、键名传空,代码主动抛异常防护

4、编码方式和读取方式不匹配,出现乱码、读取不全

5、删除逻辑混淆:清空节点、删除键、删除整节点三种逻辑不同