c#操作ini文件_增删查功能的帮助类

前言

当大家搜索ini的时候就说明项目中是需要存放一些持久性变量,或者是代码程序不能满足的数据,或者是用户及程序的配置信息,不管怎么说,就是需要操作ini文件,直接上代码

复制代码
using MediaInfoLib;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Documents;

namespace INIFileHandler
{
    public class INIFile
    {
        private string filePath;

        private const int MaxSectionSize = 32767; // Maximum size of a single INI section

        private Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();

        [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);

        [DllImport("kernel32", CharSet = CharSet.Unicode)]
        private static extern int GetPrivateProfileSection(string section, IntPtr keyValuePtr, int size, string filePath);

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

        public INIFile(string filePath)
        {
            if (!Directory.Exists(Path.GetDirectoryName(filePath)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(filePath));
                if (!File.Exists(filePath))// 判断文件是否存在,不存在则创建文件
                {
                    File.Create(filePath);
                }
            }
            this.filePath = filePath;
            Load(this.filePath);
        }

        //是否有内容
        public bool IsFileNotEmpty()
        {
            using (StreamReader reader = new StreamReader(this.filePath))
            {
                return !reader.EndOfStream;
            }
        }
        //获取文件夹下所有的文件 这个和this.filePath不一样的,这是我项目需要的另外一个路径判断
        public string[] GetFileNames(string path)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
                if (!File.Exists(path))
                {
                    File.Create(path);
                }
            }

            string[] fileNames = Directory.GetFiles(path);
            return fileNames;
        }

        //
        public void WriteValue(string section, string key, string value)
        {
            WritePrivateProfileString(section, key, value, this.filePath);

        }

        //
        public string ReadValue(string section, string key)
        {
            StringBuilder retVal = new StringBuilder(255);
            GetPrivateProfileString(section, key, "", retVal, 255, this.filePath);
            return retVal.ToString();
        }

        //通过遍历value值获取key
        public string FindKeyByValue(string value)
        {

            foreach (var kvp in keyValuePairs)
            {
                if (kvp.Value == value)
                {
                    return kvp.Key;
                }
            }

            return null; // 如果找不到对应的key,则返回null
        }

        //通过节点获取key值
        public List<string> ReadKeys(string section)
        {
            var keyValuePtr = Marshal.AllocCoTaskMem(MaxSectionSize * sizeof(char));
            try
            {
                var keyValueLength = GetPrivateProfileSection(section, keyValuePtr, MaxSectionSize, this.filePath);
                if (keyValueLength > 0)
                {
                    var keyValues = Marshal.PtrToStringUni(keyValuePtr, keyValueLength - 1);

                    
                    var pairs = keyValues.Split('\0');
                    var keys = new List<string>();
                    foreach (var pair in pairs)
                    {
                        var key = pair.Split('=')[0];
                        if (!string.IsNullOrWhiteSpace(key))
                            keys.Add(key);
                    }

                    return keys;
                }
            }
            finally
            {
                Marshal.FreeCoTaskMem(keyValuePtr);
            }

            return new List<string>();
        }

        //获取所有的section  这是我自己项目,节点一般三个字固定的,我这里是写死的,你们看自己需求测试
        public List<string> ReadSections(string filePath)
        {
            List<string> result = new List<string>();
            List<string> resultJD = new List<string>();
            Byte[] buf = new Byte[65536];
            int len = GetPrivateProfileString(null,null,null,buf, buf.Length, this.filePath);
            int j = 0;
            for (int i = 0; i < len*2; i++)
            {
                if (buf[i] == 0)
                {
                    result.Add(Encoding.UTF8.GetString(buf, j, i - j));
                    j = i + 1;
                }
            }
            string[] strArray = result.Where(s => !string.IsNullOrEmpty(s)).ToArray();
            for (int i = 0; i < strArray.Length; i += 3)
            {
                if (i + 2 < strArray.Length)
                {
                    resultJD.Add(strArray[i] + strArray[i + 1] + strArray[i + 2]);
                }
                else
                {
                    // 最后一次组成少于三位元素,不组成
                }
            }
            return resultJD;
        }

        public void DeleteSection(string section)
        {
            WritePrivateProfileString(section, null, null, this.filePath);
        }
     //这个是帮助类中构造函数的一个方法
        private void Load(string filePath)
        {
            string[] lines = File.ReadAllLines(this.filePath, Encoding.UTF8);

            foreach (string line in lines)
            {
                string trimmedLine = line.Trim();

                if (trimmedLine.StartsWith(";") || string.IsNullOrWhiteSpace(trimmedLine))
                {
                    continue;
                }

                int equalsIndex = trimmedLine.IndexOf("=");
                if (equalsIndex > 0 && equalsIndex < trimmedLine.Length - 1)
                {
                    string key = trimmedLine.Substring(0, equalsIndex).Trim();
                    string value = trimmedLine.Substring(equalsIndex + 1).Trim();

                    if (!keyValuePairs.ContainsKey(key))
                    {
                        keyValuePairs.Add(key, value);
                    }
                }
            }
        }

// 写入键值对到 INI 文件
public void WriteToIniFile(string filePath, string key, string value)
{
using (StreamWriter writer = new StreamWriter(filePath, true))
{
writer.WriteLine($"{key}={value}");
}
}


// 通过键获取 INI 文件中的值
public string GetValueFromIniFile(string filePath, string key)
{
using (StreamReader reader = new StreamReader(filePath))
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.StartsWith(key + "="))
{
return line.Substring(key.Length + 1);
}
}
}
return null;
}


// 清空 INI 文件内容
public void ClearIniFile(string filePath)
{
File.WriteAllText(filePath, string.Empty);
}


    }
}

复制代码

 上面代码发现不能读写有中文的字,后查阅资料发现ini文件本身是ASCII编码格式的文件,但是我使用C#中的 Encoding.ASCII去指定编码读取ini文件中内容,发现是问号?乱码,经过改进,将传入的key和value直接指定为utf-8的格式写入,该ini文件就为nuf-8编码的格式了,读取也是这个格式,成功读取出来

复制代码
 1         [DllImport("kernel32")]
 2         private static extern long WritePrivateProfileString(string section,
 3             byte[] key, byte[] val, string filePath);
 4         
 5         [DllImport("kernel32")]
 6         private static extern int GetPrivateProfileString(string section,
 7                  string key, string def, Byte[] retVal,
 8                  int size, string filePath);
 9 
10 //
11         public void WriteValue(string section, string key, string value)
12         {
13             WritePrivateProfileString(section, Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(value), this.filePath);
14 
15         }
16 
17         //
18         public string ReadValue(string section, string key)
19         {
20             /*StringBuilder retVal = new StringBuilder(2550);
21             GetPrivateProfileString(section, key, "", retVal, 2550, this.filePath);
22             return retVal.ToString();*/
23 
24             byte[] Buffer = new byte[1024];
25             int bufLen = GetPrivateProfileString(section, key, "", Buffer, Buffer.GetUpperBound(0), this.filePath);
26             string s = Encoding.UTF8.GetString(Buffer, 0, bufLen);
27             return s;
28         }        
复制代码

 

posted @   山中修炼十余载  阅读(188)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示