知者何南 发表于 2025-3-5 16:33:16

C#读写ini文件

C#读写ini文件

调用winAPI 实现ini文件操作

[*]dll路径:C:\Windows\System32\kernel32.dll;
[*]若调用失败可查看dll是否存在以及环境变量(C:\Windows\System32)是否已设置
[*]静态类编写如下
文件接纳默认路径,若需要改变,调用之前请先更新文件路径
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace BasicExercises
{
    /***
   *ini文件样式
   *[配置项]
   *属性1 = 属性值
   *属性2 = 属性值
   *...
   *
   *CharSet定义的时候使用了什么类型,在使用相关方法时必须要使用相应的类型
   *      例如 GetPrivateProfileSectionNames声明为CharSet.Auto,那么就应该使用 Marshal.PtrToStringAuto来读取相关内容
   *      如果使用的是CharSet.Ansi,就应该使用Marshal.PtrToStringAnsi来读取内容
   * **/
    class IniConfigHelper
    {
      static string iniFilePath = Environment.CurrentDirectory+"config.ini";
      public static string IniFilePath { get => iniFilePath; set => iniFilePath = value; }


      /***
         * 调用winAPI 实现ini文件操作
         * dll路径:C:\Windows\System32\kernel32.dll,若调用失败可查看dll是否存在以及环境变量(C:\Windows\System32)是否已设置
         * 以下是API函数
      ***/


      /// <summary>
      /// 写入ini文件:将指定的键和值写到指定的节点,如果已经存在则替换
      /// </summary>
      /// <param name="section">节点名称</param>
      /// <param name="key">键,null也直接写入</param>
      /// <param name="value">值,null也直接写入</param>
      /// <param name="filePath">ini文件路径</param>
      /// <returns>0失败/其他成功</returns>
      //
      //private static extern long WritePrivateProfileString(string section, string key, string value, string filePath);

      /// <summary>
      /// 写入ini文件:将指定的键和值写到指定的节点,如果已经存在则替换
      /// </summary>
      /// <param name="section">节点名称</param>
      /// <param name="key">键,null则删除指定的节点及其所有的项目</param>
      /// <param name="value">值,null则删除指定节点中指定的键</param>
      /// <param name="filePath">ini文件路径</param>
      /// <returns>操作是否成功</returns>
      
      private static extern bool WritePrivateProfileString(string section, string key, string value, string filePath);


      /// <summary>
      /// 将指定的键值对写到指定的节点,如果已经存在则替换。
      /// </summary>
      /// <param name="section">节点,如果不存在此节点,则创建此节点</param>
      /// <param name="keyValue">Item键值对,多个用\0分隔,形如key1=value1\0key2=value2
      ///   如果为string.Empty,则删除指定节点下的所有内容,保留节点
      ///   如果为null,则删除指定节点下的所有内容,并且删除该节点
      ///   该方法无脑写入,遇"\0"换行写入
      /// </param>
      /// <param name="filePath"></param>
      /// <returns>操作成功与否</returns>
      
      private static extern bool WritePrivateProfileSection(string section, string keyValue, string filePath);

      /// <summary>
      /// 调用winAPI读取ini文件
      /// </summary>
      /// <param name="section">节点名称</param>
      /// <param name="key">键</param>
      /// <param name="def">值(未读取到数据时设置的默认返回值)</param>
      /// <param name="result">读取的结构值</param>
      /// <param name="size">读取的缓冲区大小</param>
      /// <param name="filePath">ini路径</param>
      /// <returns>读取到的字节数量</returns>
      
      private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder result, int size, string filePath);

      /// <summary>
      /// 获取所有节点名称(Section)
      /// </summary>
      /// <param name="ptrResultBuffer">存放节点名称的内存地址,每个节点之间使用\0分隔</param>
      /// <param name="nSize">内存大小</param>
      /// <param name="filePath">ini文件路径</param>
      /// <returns>内容的实际长度,为0表示没有内容,为nSize-2表示内存大小不够</returns>
      
      private static extern uint GetPrivateProfileSectionsNames(IntPtr lpResultBuffer,uint nSize,string filePath);

      /// <summary>
      /// 获取某个指定节点(Section)中所有KEY和Value
      /// </summary>
      /// <param name="section">节点名称</param>
      /// <param name="lpReturnedString">返回值的内存地址,每个之间使用\0分隔</param>
      /// <param name="nSize">内存大小</param>
      /// <param name="filePath">ini文件地址</param>
      /// <returns></returns>
      
      private static extern uint GetPrivateProfileSection(string section, IntPtr lpReturnedString, uint nSize, string filePath);


      /***
         * 调用winAPI 实现ini文件操作
         * 以下是API对应的调用函数封装
      ***/

      /// <summary>
      /// 写入ini,指定节点下单键值对写入
      /// </summary>
      /// <param name="section"></param>
      /// <param name="key"></param>
      /// <param name="value"></param>
      /// <returns>操作成功与否</returns>
      public static boolWriteToIni(string section, string key, string value)
      {
            if (string.IsNullOrEmpty(section))
            {
                return false;
                //throw new ArgumentException("必须指定节点名称",section);
            }
            if (string.IsNullOrEmpty(key))
            {
                return false;
                //throw new ArgumentException("必须指定key值",key);
            }
            if (string.IsNullOrEmpty(value))
            {
                return false;
                //throw new ArgumentException("值不能为空",value);
            }
            return WritePrivateProfileString(section, key, value, iniFilePath);
      }

      /// <summary>
      /// 删除指定节点下指定键
      /// </summary>
      /// <param name="section">节点</param>
      /// <param name="key">键</param>
      /// <returns>操作成功与否</returns>
      public static bool DeleteKey(string section, string key)
      {
            if (string.IsNullOrEmpty(section))
            {
                return false;
                //throw new ArgumentException("必须指定节点名称",section);
            }
            if (string.IsNullOrEmpty(key))
            {
                return false;
                //throw new ArgumentException("必须指定key值",key);
            }
            return WritePrivateProfileString(section, key, null, iniFilePath);
      }

      /// <summary>
      /// 删除指定节点
      /// </summary>
      /// <param name="section">节点</param>
      /// <returns>操作成功与否</returns>
      public static bool DeleteSection(string section)
      {
            if (string.IsNullOrEmpty(section))
            {
                return false;
                //throw new ArgumentException("必须指定节点名称",section);
            }
            return WritePrivateProfileString(section, null, null, iniFilePath);
      }

      /// <summary>
      /// 清空指定节点
      /// </summary>
      /// <param name="section">节点</param>
      /// <returns>操作成功与否</returns>
      publicstaticbool EmptySection(string section)
      {
            if (string.IsNullOrEmpty(section))
            {
                return false;
                //throw new ArgumentException("必须指定节点名称",section);
            }
            return WritePrivateProfileSection(section,string.Empty,iniFilePath);
      }

      /// <summary>
      /// 写入ini,指定节点下多个键值对写入
      /// </summary>
      /// <param name="section">节点</param>
      /// <param name="keyValue">键值对,形如key1=value1\0key2=value2 </param>
      /// <returns></returns>
      public static bool WriteToIniSection(string section, string keyValue)
      {
            if (string.IsNullOrEmpty(section))
            {
                return false;
                //throw new ArgumentException("必须指定节点名称",section);
            }
            if (string.IsNullOrEmpty(keyValue))
            {
                return false;
                //throw new ArgumentException("键值对不能为空",keyValue);
            }
            return WritePrivateProfileSection(section, keyValue, iniFilePath);
      }

      
      /// <summary>
      /// 读取ini,section和key不能为null
      /// </summary>
      /// <param name="section">节点</param>
      /// <param name="key">键</param>
      /// <returns>null或读取结果</returns>
      public static string ReadFromIni(string section,string key)
      {
            if (string.IsNullOrEmpty(section))
            {
                return null;
                //throw new ArgumentException("必须指定节点名称", section);
            }
            if (string.IsNullOrEmpty(key))
            {
                return null;
                //throw new ArgumentException("必须指定key值", key);
            }
            int size = 1024;
            StringBuilder builder = new StringBuilder(size);
            //string def = "";
            int result = GetPrivateProfileString(section, key, "", builder, size, iniFilePath);
            return builder.ToString();
      }


      /// <summary>
      /// 获取ini文件所有节点
      /// </summary>
      /// <returns>所有节点,没有内容返回string</returns>
      public static string[] GetAllSections()
      {
            uint MAX_BUFFER = 32767;
            string[] sections = new string;
            //申请内存
            IntPtr pReturnedStr = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));
            //读取内容
            uint nSize = GetPrivateProfileSectionsNames(pReturnedStr, MAX_BUFFER, iniFilePath);
            if (nSize != 0 && nSize != MAX_BUFFER - 2)
            {
                //读取内存内存
                string returnedStr = Marshal.PtrToStringAuto(pReturnedStr, (int)nSize);
                //转换成string[]格式
                sections = returnedStr.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
            }
            //释放内存
            Marshal.FreeCoTaskMem(pReturnedStr);
            return sections;

      }

      /// <summary>
      /// 获取指定节点下的所有key、value;形式key=value
      /// </summary>
      /// <param name="section">指定节点</param>
      /// <returns>指定节点的所有条目,空则返回string</returns>
      public static string[] GetAllKeyValueBySection(string section)
      {
            if (string.IsNullOrEmpty(section))
            {
                return null;
                //throw new ArgumentException("必须指定节点名称", section);
            }
            uint MAX_BUFFER = 32767;
            string[] items = new string;
            //分配内存
            IntPtr pReturnedStr = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));

            uint nSize = GetPrivateProfileSection(section, pReturnedStr, MAX_BUFFER, iniFilePath);
            if (nSize != 0 && nSize != MAX_BUFFER - 2)
            {
                //读取内存内容
                string returnedStr = Marshal.PtrToStringAuto(pReturnedStr, (int)nSize);
                每个节点之间用\0分隔,末尾有一个\0
                items = returnedStr.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
            }
            //释放内存
            Marshal.FreeCoTaskMem(pReturnedStr);
            return items;
      }
    }
}


[*]调用窗口:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace BasicExercises
{
    public partial class TestForm : Form
    {
      public TestForm()
      {
            InitializeComponent();
      }

      private void btnTestIni_Click(object sender, EventArgs e)
      {
            
            string userSection = "用户";
            string userNameKey = "Name";

            string testSection = "测试节点";
            string keyValue = "用户1=苏\0密码=苏\0用户2=林\0密码=林";

            //ini写入
            txtBoxMsg.Text = "";
            txtBoxMsg.Text += "测试写入以下内容:\r\n[" + userSection + "]\r\n" + userNameKey + " = 测试用户";
            bool IsWriteSec = IniConfigHelper.WriteToIni(userSection, userNameKey, "测试用户");
            if (IsWriteSec)
            {
                txtBoxMsg.Text += "\r\n写入成功!";
            }

            //多个键值对写入
            // \0 在C#中代表结束字符,不会被窗体输出
            txtBoxMsg.Text += "\r\n" + keyValue;
            IsWriteSec = IniConfigHelper.WriteToIniSection(testSection, keyValue);
            if (IsWriteSec)
            {
                txtBoxMsg.Text += "\r\n写入成功!";
            }

            //ini读取指定键
            string value = IniConfigHelper.ReadFromIni(userSection, userNameKey);
            txtBoxMsg.Text += "\r\n读取结果:" + value;

            //获取ini所有节点
            string[] sectionItems = IniConfigHelper.GetAllKeyValueBySection(testSection);
            string allSection = "";
            foreach (string item in sectionItems)
            {
                allSection += item;
            }
            txtBoxMsg.Text += "\r\n获取ini所有节点:" + allSection;

            //获取ini指定节点下的所有key和value
            string[] items = IniConfigHelper.GetAllKeyValueBySection(testSection);
            string msg = "";
            foreach (string item in items)
            {
                msg += item;
            }
            txtBoxMsg.Text += "\r\n获取ini指定节点下的所有key和value:" + msg;

            //删除指定key
            IsWriteSec = IniConfigHelper.DeleteKey(userSection, userNameKey);
            if (IsWriteSec)
            {
                txtBoxMsg.Text += "\r\n删除" + "[" + userSection + "]下的键:" + userNameKey + "成功";
            }


            //删除指定节点
            IsWriteSec = IniConfigHelper.DeleteSection(userSection);
            if (IsWriteSec)
            {
                txtBoxMsg.Text += "\r\n删除" + "[" + userSection + "]节点成功";
            }
            IsWriteSec = IniConfigHelper.DeleteSection(testSection);
            if (IsWriteSec)
            {
                txtBoxMsg.Text += "\r\n删除" + "[" + testSection + "]节点成功";
            }

      }
    }
}

https://i-blog.csdnimg.cn/direct/6193f83141a84f8aad2b3ac0a270b603.png

[*]运行结果:
https://i-blog.csdnimg.cn/direct/1ab2b22e1f7c410fab452988a2f03a1e.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: C#读写ini文件