C#读写ini文件

C#读写ini文件

调用winAPI 实现ini文件操作

  1. dll路径:C:\Windows\System32\kernel32.dll;
  2. 若调用失败可查看dll是否存在以及环境变量(C:\Windows\System32)是否已设置
  3. 静态类编写如下
    文件采用默认路径,若需要改变,调用之前请先更新文件路径
csharp 复制代码
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>
        //[DllImport("kernel32", CharSet = CharSet.Auto)]
        //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>
        [DllImport("kernel32", CharSet = CharSet.Auto)]
        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>
        [DllImport("kernel32", CharSet = CharSet.Auto)]
        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>
        [DllImport("kernel32", CharSet = CharSet.Auto)]
        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>
        [DllImport("kernel32", CharSet = CharSet.Auto)]
        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>
        [DllImport("kernel32", CharSet = CharSet.Auto)]
        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 bool  WriteToIni(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>
        public  static  bool 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[0]</returns>
        public static string[] GetAllSections()
        {
            uint MAX_BUFFER = 32767;
            string[] sections = new string[0];
            //申请内存
            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[0]</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[0];
            //分配内存
            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;
        }
    }
}
  1. 调用窗口:
csharp 复制代码
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 + "]节点成功";
            }

        }
    }
}
  1. 运行结果:
相关推荐
Yang-Never1 分钟前
OpenGL ES -> GLSurfaceView纹理贴图
android·java·开发语言·kotlin·android studio·贴图
至暗时刻darkest9 分钟前
Go 接口使用
开发语言·后端·golang
Maryhuan10 分钟前
【开源-常用C/C++命令行解析库对比】
c语言·开发语言·c++
进击的_鹏29 分钟前
【C++】stack和queue以及priority_queue的使用以及模拟实现
开发语言·c++·算法
SomeB1oody30 分钟前
【Python机器学习】1.1. 机器学习(Machine Learning)介绍
开发语言·人工智能·python·机器学习
李钢蛋31 分钟前
PHP对接微信支付v3版本
开发语言·微信·php
Ai 编码助手1 小时前
Python 如何实现烟花效果的完整代码
开发语言·python·pygame
独坐寒江边1 小时前
如何在Python用Plot画出一个简单的机器人模型
开发语言·python·机器人
心灵宝贝1 小时前
Linux中jdk-8u291-linux-x64 中jdk工具包
java·linux·开发语言
Tiger Z1 小时前
R 语言科研绘图第 29 期 --- 密度图-山脊线
开发语言·程序人生·r语言·贴图