/* ---------------------------------------------------------- * 文件名称:LINQToINI.cs * * 作者:秦建辉 * * 微信:splashcn * * 博客:http://www.firstsolver.com/wordpress/ * * 开发环境: * Visual Studio V2015 * .NET Framework 4 Client Profile * * 版本历史: * V1.2 2016年07月30日 * 更新GetProfileSection方法输出 * * V1.1 2012年11月14日 * 存储文件时,如果目录不存在,则自动创建目录而不是返回失败 * * V1.0 2011年06月30日 * 基于LINQ实现对ini文件的读写 ------------------------------------------------------------ */ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace JwKdsV.Core.HWiNFO { /// /// 基于LINQ实现对ini文件的读写 /// internal class LINQToINI { /// /// ini文件内容结点结构 /// private struct ININode { /// /// 分区名 /// public string section; /// /// 键名 /// public string keyName; /// /// 键值 /// public string keyValue; } /// /// ini文件内容结点列表 /// private List INIElement = null; /// /// 读取ini文件并序列化,以供LINQ查询 /// /// ini文件名 /// 是否只做查询操作。缺省为true /// 文件编码,缺省为null,使用Unicode编码 /// /// true:成功 /// false:失败 /// /// /// 如果只做查询操作,则序列化时去掉空行结点和注释行结点 /// public bool Load(string iniFile, bool isQueryOnly = true, Encoding fileEncoding = null) { if (fileEncoding == null) { // 默认使用Unicode编码 fileEncoding = Encoding.Unicode; } try { // 自动检测文件编码 using (StreamReader sr = new StreamReader(iniFile, fileEncoding, true)) { if (INIElement == null) { INIElement = new List(); } else { INIElement.Clear(); } string Section = null; while (true) { string Source = sr.ReadLine(); if (Source == null) break; Source = Source.Trim(); if (Source == string.Empty) { // 空行 if (!isQueryOnly) { INIElement.Add(new ININode { section = "\u000A", keyName = null, keyValue = null }); } } else if (Source[0] == '#' || Source[0] == ';') { // 注释行 if (!isQueryOnly) { INIElement.Add(new ININode { section = "\u000B", keyName = null, keyValue = Source }); } } else if (Source[0] == '[') { // 分区名 int RightSquareBracketIndex = Source.IndexOf(']'); if (RightSquareBracketIndex != -1) { Section = Source.Substring(1, RightSquareBracketIndex - 1).Trim(); if (Section != string.Empty) { INIElement.Add(new ININode { section = Section, keyName = string.Empty, keyValue = null }); } } } else { // 键名键值对 if (!string.IsNullOrEmpty(Section)) { int EqualsSignIndex = Source.IndexOf('='); if (EqualsSignIndex != -1) { // 提取键名 string KeyName = Source.Substring(0, EqualsSignIndex).Trim(); if (KeyName != string.Empty) { // 提取键值 string KeyValue = Source.Substring(EqualsSignIndex + 1).Trim(); if (KeyValue.Length >= 2) { // 判断是否有双引号 if (KeyValue[0] == '\u0022' && KeyValue[KeyValue.Length - 1] == '\u0022') { KeyValue = KeyValue.Substring(1, KeyValue.Length - 2); } } INIElement.Add(new ININode { section = Section, keyName = KeyName, keyValue = KeyValue }); } } } } } return true; } } catch (System.Exception) { return false; } } /// /// 存储ini文件 /// /// 要存储的文件名 /// 文件编码。缺省为null,使用Unicode编码 /// /// true:成功 /// false:失败 /// /// 注意:只有调用此函数,才能保存最终数据 public bool Save(string iniFile, Encoding fileEncoding = null) { if (INIElement == null) { // 抛出异常:无效的数据源 throw new ApplicationException("Invalid Data Source!"); } if (fileEncoding == null) { // 默认使用Unicode编码 fileEncoding = Encoding.Unicode; } try { // 获取指定字符串的目录信息 string ToFolder = Path.GetDirectoryName(iniFile); // 注意相对路径 if (!string.IsNullOrEmpty(ToFolder) && !Directory.Exists(ToFolder)) { // 目录不存在,创建目录 Directory.CreateDirectory(ToFolder); } // 写入文件 using (StreamWriter sw = new StreamWriter(iniFile, false, fileEncoding)) { foreach (ININode node in INIElement) { if (node.keyName == null) { if (node.section == "\u000A") { // 空行 sw.WriteLine(); } else if (node.section == "\u000B") { // 注释行 sw.WriteLine(node.keyValue); } } else { if (node.keyName == string.Empty) { // 分区 sw.WriteLine("[" + node.section + "]"); } else { // 键名键值对 if (node.keyValue.IndexOf(' ') == -1) { // 键值中没有空格 sw.WriteLine(node.keyName + "=" + node.keyValue); } else { // 键值中包含空格,需在键值两端加上引号 sw.WriteLine(node.keyName + "=\u0022" + node.keyValue + "\u0022"); } } } } return true; } } catch (System.Exception) { return false; } } /// /// 提取键名对应的键值 /// /// 分区名。如果为null,则提取所有的分区名 /// 键名。如果为null,则提取分区所有的键名键值对 /// 缺省键值 /// 键值 public string[] GetProfileString(string section, string keyName, string defaultString = null) { if (INIElement == null) { // 抛出异常:无效的数据源 throw new ApplicationException("Invalid Data Source!"); } if (section == null) { // 获取所有的分区名 return (from node in INIElement where (node.keyName == string.Empty) select node.section).ToArray(); } else if (keyName == null) { // 获取指定分区所有的键名及键值 return (from node in INIElement where (string.Compare(node.section, section, true) == 0 && !string.IsNullOrEmpty(node.keyName)) select (node.keyName + "=" + node.keyValue)).ToArray(); } else { // 获取键值 var ValueQuery = (from node in INIElement where (string.Compare(node.section, section, true) == 0 && string.Compare(node.keyName, keyName, true) == 0) select node.keyValue).ToArray(); if (ValueQuery.Length == 0) { return new string[] { defaultString }; } else { return ValueQuery; } } } /// /// 提取键名对应的键值(整数值) /// /// 分区名 /// 键名 /// 缺省键值,默认为0 /// 键值(整数值) public int GetProfileInt(string section, string keyName, int defaultValue = 0) { if (INIElement == null) { // 抛出异常:无效的数据源 throw new ApplicationException("Invalid Data Source!"); } if (string.IsNullOrEmpty(section) || string.IsNullOrEmpty(keyName)) { return defaultValue; } // 获取键值 var ValueQuery = (from node in INIElement where (string.Compare(node.section, section, true) == 0 && string.Compare(node.keyName, keyName, true) == 0) select node.keyValue).ToArray(); if (ValueQuery.Length == 0) { return defaultValue; } else { if (ValueQuery[0] == string.Empty) { return defaultValue; } else { // 将字符串转换为整数值(注意:可能会抛出异常) return Convert.ToInt32(ValueQuery[0]); } } } /// /// 获取分区所有的键名键值对 /// /// 分区名 /// 键名键值对数组 public KeyValuePair[] GetProfileSection(string section) { if (INIElement == null) { // 抛出异常:无效的数据源 throw new ApplicationException("Invalid Data Source!"); } if (string.IsNullOrEmpty(section)) { return null; } else { // 获取指定分区所有的键名及键值 return (from node in INIElement where (string.Compare(node.section, section, true) == 0 && !string.IsNullOrEmpty(node.keyName)) select (new KeyValuePair(node.keyName, node.keyValue))).ToArray(); } } /// /// 获取所有的分区名 /// /// 分区名数组 public string[] GetProfileSectionNames() { if (INIElement == null) { // 抛出异常:无效的数据源 throw new ApplicationException("Invalid Data Source!"); } // 获取所有的分区名 return (from node in INIElement where (string.Compare(node.keyName, string.Empty, true) == 0) select node.section).ToArray(); } /// /// 增加或更新分区名、键名或者键值 /// /// 分区名 /// 键名。如果为null或者空串,则删除整个分区 /// 键值。如果为null,则删除该键 /// /// true:成功 /// false:失败 /// public bool WriteProfileString(string section, string keyName, string keyValue) { if (string.IsNullOrEmpty(section)) { return false; } if (INIElement == null) { // 初始化ini结点列表 INIElement = new List(); } if (string.IsNullOrEmpty(keyName)) { // 删除整个分区(关键:要从后往前删) for (int i = INIElement.Count - 1; i >= 0; i--) { if (string.Compare(INIElement[i].section, section, true) == 0 && INIElement[i].keyName != null) { INIElement.RemoveAt(i); } } } else { // 更新键值 int InsertIndex = -1; for (int i = INIElement.Count - 1; i >= 0; i--) { if (string.Compare(INIElement[i].section, section, true) == 0) { if (string.Compare(INIElement[i].keyName, keyName, true) == 0) { // 删除该键 INIElement.RemoveAt(i); if (keyValue != null) { // 更新该键 if (keyValue.Length >= 2) { // 判断是否有双引号 if (keyValue[0] == '\u0022' && keyValue[keyValue.Length - 1] == '\u0022') { keyValue = keyValue.Substring(1, keyValue.Length - 2); } } // 插入更新后的键名键值对 INIElement.Insert(i, new ININode { section = section, keyName = keyName, keyValue = keyValue }); } // 直接返回 return true; } if (InsertIndex == -1) { // 将分区末尾做为插入点 InsertIndex = i + 1; } } } if (InsertIndex == -1) { // 分区不存在,首先增加新的分区名 INIElement.Add(new ININode { section = section, keyName = string.Empty, keyValue = null }); // 再增加新的键名键值对 INIElement.Add(new ININode { section = section, keyName = keyName, keyValue = keyValue }); } else { // 分区存在,在分区末尾增加新的键名键值对 INIElement.Insert(InsertIndex, new ININode { section = section, keyName = keyName, keyValue = keyValue }); } } return true; } /// /// 替换分区的键名键值对 /// /// 分区名 /// 要替换的键名键值对。如果为null,则删除整个分区 /// /// true:成功 /// false:失败 /// public bool WriteProfileSection(string section, string[] keyValueSet) { if (string.IsNullOrEmpty(section)) { return false; } if (INIElement == null) { // 初始化ini结点列表 INIElement = new List(); } // 删除整个分区 int InsertIndex = INIElement.Count; for (int i = INIElement.Count - 1; i >= 0; i--) { if (string.Compare(INIElement[i].section, section, true) == 0 && INIElement[i].keyName != null) { INIElement.RemoveAt(i); InsertIndex = i; } } if (keyValueSet != null) { // 写入分区名 INIElement.Insert(InsertIndex++, new ININode { section = section, keyName = string.Empty, keyValue = null }); // 写入键名键值对 foreach (string s in keyValueSet) { int EqualsSignIndex = s.IndexOf('='); if (EqualsSignIndex != -1) { string KeyName = s.Substring(0, EqualsSignIndex).Trim(); if (KeyName != string.Empty) { string KeyValue = s.Substring(EqualsSignIndex + 1).Trim(); if (KeyValue.Length >= 2) { // 判断是否有双引号 if (KeyValue[0] == '\u0022' && KeyValue[KeyValue.Length - 1] == '\u0022') { KeyValue = KeyValue.Substring(1, KeyValue.Length - 2); } } INIElement.Insert(InsertIndex++, new ININode { section = section, keyName = KeyName, keyValue = KeyValue }); } } } } return true; } /// /// 将结构数据写入键值 /// /// 分区名 /// 键名 /// 数据 /// /// true:成功 /// false:失败 /// public bool WriteProfileStruct(string section, string keyName, byte[] data) { if (string.IsNullOrEmpty(section) || string.IsNullOrEmpty(keyName)) { return false; } if (data == null) { return WriteProfileString(section, keyName, null); } // 将字节数组转换成16进制字符串 StringBuilder sb = new StringBuilder((data.Length + 1) << 1); int CheckSum = 0; foreach (byte b in data) { CheckSum += b; sb.Append(b.ToString("X2")); } // 写入校验和 sb.Append(((byte)CheckSum).ToString("X2")); return WriteProfileString(section, keyName, sb.ToString()); } /// /// 提取键值,并转化为字节数组 /// /// 分区名 /// 键名 /// 键值对应的字节数组 public byte[] GetProfileStruct(string section, string keyName) { if (INIElement == null) { // 抛出异常:无效的数据源 throw new ApplicationException("Invalid Data Source!"); } if (string.IsNullOrEmpty(section) || string.IsNullOrEmpty(keyName)) { return null; } // 获取键值 var ValueQuery = (from node in INIElement where (string.Compare(node.section, section, true) == 0 && string.Compare(node.keyName, keyName, true) == 0) select node.keyValue).ToArray(); if (ValueQuery.Length != 1) { return null; } // 将16进制字符串转换成字节数组 string s = ValueQuery[0]; if (string.IsNullOrEmpty(s) || (s.Length % 2 != 0)) { return null; } try { int Num = s.Length / 2 - 1; byte[] ValueArray = new byte[Num]; int CheckSum = 0; for (int i = 0; i < Num; i++) { CheckSum += ValueArray[i] = Convert.ToByte(s.Substring(i << 1, 2), 16); } // 检测校验和 if (Convert.ToByte(s.Substring(Num << 1, 2), 16) == CheckSum) { return ValueArray; } else { // 校验失败 return null; } } catch (System.Exception) { // 无效字符串 return null; } } } }