• C#实现读写ini文件,非调用系统方法


    项目里用了很多ini配置文件,并且读写非常频繁。

    之前一直用的是调用系统的方法

    1         private readonly string _inipath;
    2         [DllImport("kernel32", CharSet = CharSet.Auto)]
    3         private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
    4 
    5         [DllImport("kernel32", CharSet = CharSet.Auto)]
    6         private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

    但最近要改进项目支持维语,发现ini的读写就有问题了

    首先是系统的方法不认识维语的文件名

    后来花了大把的力气,把文件名改成英文的,结果发现,不能正常读取和写入

    无耐只能放弃使用系统的读取方法,在博客园里找到  @幸福★星  https://www.cnblogs.com/xingfustar/archive/2007/09/13/891950.html

    这篇博文,就拿来用了,在这里感谢一下@幸福★星

    放上去后简单测试发现,效率很低,因为项目里的配置文件多且每个文件的配置项也很多,频繁读取和保存导致系统很卡

    就在这个代码上做了一下优化,见正面的代码:

      1  /*----------------------------------------------------------------
      2      * http://XingFuStar.cnblogs.com
      3      *---------------------------------------------------------------*/
      4   /*----------------------------------------------------------------
      5      * 
      6      * 为保证代码的正确性,对INI文件做如下要求:
      7      * 1、以";"开头代表注释,注释要另起一行,不要使用非";"开头的注释
      8      * 2、如果使用了非";"开头的注释,该行中不要包括“=”
      9      * 3、如果使用了非";"开头的注释,对INI进行设置生,该行会被删除
     10      * 
     11      *---------------------------------------------------------------*/
     12         public class IniConfig
     13         {
     14             private string iniPath = "";
     15             private bool isConfig;
     16             private Dictionary<string, List<Property>> propertyList;
     17 
     18             /// <summary>
     19             /// 构造函数:装载配置文件
     20             /// </summary>
     21             /// <param name="iniPath">配置文件的路径</param>
     22             public IniConfig(string iniPath)
     23             {
     24                 this.IniPath = iniPath;
     25             }
     26 
     27             public string IniPath
     28             {
     29                 set
     30                 {
     31                     iniPath = value;
     32                     isConfig = OnIniPataChanged();
     33                 }
     34             }
     35 
     36 
     37             /// <summary>
     38             /// 读取Ini中的配置
     39             /// </summary>
     40             /// <param name="section">节点</param>
     41             /// <param name="key"></param>
     42             /// <returns>读取值</returns>
     43             public string ReadValue(string section, string key)
     44             {
     45                 string value = "";
     46                 bool isRead = false;
     47                 try
     48                 {
     49                     if (propertyList != null && propertyList.ContainsKey(section))
     50                     {
     51                         Property item = propertyList[section].FirstOrDefault(p => p.Key == key);
     52                         if (item != null) return item.Value;
     53                     }
     54                 }
     55                 catch (Exception ex)
     56                 {
     57                     Debug.Print(ex.Message);
     58                 }
     59                 return value;
     60             }
     61 
     62             /// <summary>
     63             /// 向INI中写入配置
     64             /// </summary>
     65             /// <param name="section">节点</param>
     66             /// <param name="key"></param>
     67             /// <param name="value">要写入的新键值</param>
     68             /// <returns>写入是否成功</returns>
     69             public void WriteValue(string section, string key, string value)
     70             {
     71                 bool isWrite = false;
     72                 try
     73                 {
     74                     if (isConfig)
     75                     {
     76                         InitSection(section);
     77                         Property item = propertyList[section].FirstOrDefault(p => p.Key == key);
     78                         if (item != null)
     79                         {
     80                             item.Value = value;
     81                         }
     82                         else
     83                         {
     84                             item = new Property(key,value,""); 
     85                             propertyList[section].Add(item);
     86                         }
     87                         StartSaveIni();
     88                         
     89 
     90                     }
     91                 }
     92                 catch (Exception ex)
     93                 {
     94                     Debug.Print(ex.Message);
     95                 }
     96                // return isWrite;
     97             }
     98 
     99             private long _savingThreads = 0;//是否在执行写入中
    100             private void StartSaveIni()
    101             {
    102                 Action action = () =>
    103                 {
    104                     if (Interlocked.Read(ref _savingThreads) > 1) return;
    105                     Interlocked.Increment(ref _savingThreads);
    106                     System.Threading.Thread.Sleep((int)_savingThreads * 500);
    107                     SaveIni();
    108                     Interlocked.Decrement(ref _savingThreads);
    109                 };
    110                 action.BeginInvoke(null, null);
    111             }
    112 
    113 
    114 
    115             /// <summary>
    116             /// 移除键值对
    117             /// </summary>
    118             /// <param name="section"></param>
    119             /// <param name="key"></param>
    120             public void RemoveItem(string section, string key)
    121             {
    122                 WriteValue(section, key, null);
    123             }
    124 
    125             /// <summary>
    126             /// 验证文件是否存在
    127             /// </summary>
    128             /// <returns>布尔值</returns>
    129             public bool IsExistIniFile()
    130             {
    131                 return File.Exists(iniPath);
    132             }
    133 
    134             #region 私有方法
    135             private bool OnIniPataChanged()
    136             {
    137                 bool isLoad = false;
    138                 try
    139                 {
    140                     if (File.Exists(iniPath))
    141                     {
    142                         isLoad = LoadIni();
    143                     }
    144                 }
    145                 catch (Exception ex)
    146                 {
    147                     Debug.Print(ex.Message);
    148                 }
    149                 return isLoad;
    150             }
    151 
    152             /// <summary>
    153             /// 从文件中加载INI配置信息到列表
    154             /// </summary>
    155             /// <returns>加载是否成功</returns>
    156             private bool LoadIni()
    157             {
    158                 bool isLoad = false;
    159                 try
    160                 {
    161                     propertyList = new Dictionary<string, List<Property>>();
    162                     using (StreamReader stream = new StreamReader(iniPath, System.Text.Encoding.Unicode))
    163                     {
    164                         string section = "";
    165                         while (stream.Peek() != -1)
    166                         {
    167                             string str = stream.ReadLine().Trim();
    168                             //判断该行是否有数据
    169                             if (str.Length > 0)
    170                             {
    171                                 //以“;”开头的行为注释行(硬性规定)
    172                                 if (str.Substring(0, 1) != ";")
    173                                 {
    174                                     //以“[“开头的行为Section行(硬性规定)
    175                                     if (str.Substring(0, 1) == "[")
    176                                     {
    177                                         //记录当前Section
    178                                         section = str.Substring(1, str.IndexOf("]") - 1);
    179                                         InitSection(section);
    180                                     }
    181                                     //有“=”的为数据行(硬性规定)
    182                                     if (str.IndexOf("=") > 0 && !String.IsNullOrEmpty(section))
    183                                     {
    184                                         string[] temp = str.Split('=');
    185                                         //将该数据行的属性添加到列表
    186                                         InitSection(section);
    187                                         propertyList[section].Add(new Property(temp[0].Trim(), temp[1].Trim(), ""));
    188                                     }
    189                                 }
    190                                 else if (!String.IsNullOrEmpty(section))
    191                                 {
    192                                     //将注释行的属性添加到列表
    193                                     InitSection(section);
    194                                     propertyList[section].Add(new Property("", "", str));
    195                                 }
    196                             }
    197                             else if (!String.IsNullOrEmpty(section))
    198                             {
    199                                 InitSection(section);
    200                                 //为保证格式与加载前相同,因些将空行也加入了列表
    201                                 propertyList[section].Add(new Property("", "", ""));
    202                             }
    203                         }
    204                         stream.Close();
    205                     }
    206                     isLoad = true;
    207                 }
    208                 catch (Exception ex)
    209                 {
    210                     Debug.Print(ex.Message);
    211                 }
    212                 return isLoad;
    213             }
    214 
    215             private void InitSection(string section)
    216             {
    217                 if(propertyList == null)propertyList = new Dictionary<string, List<Property>>();
    218                 if(!propertyList.ContainsKey(section))
    219                     propertyList.Add(section,new List<Property>());
    220             }
    221 
    222             /// <summary>
    223             /// 将列表中的配置信息保存到INI文件
    224             /// </summary>
    225             /// <returns>保存是否成功</returns>
    226             private bool  SaveIni()
    227             {
    228                 bool isSave = false;
    229                 try
    230                 {
    231                     using (StreamWriter stream = new StreamWriter(iniPath, false, System.Text.Encoding.Unicode))
    232                     {
    233                         foreach (var section in propertyList)
    234                         {
    235                             stream.WriteLine("[" + section.Key + "]");
    236 
    237                             List<Property> items = section.Value;
    238                             foreach (var item in items)
    239                             {
    240                                 if(item.NeedDelete)continue;
    241                                 //写入注释
    242                                 if (item.Description != "")
    243                                 {
    244                                     stream.WriteLine(item.Description);
    245                                 }
    246                                 //写入键和键值
    247                                 if (item.Key != "")
    248                                 {
    249                                     stream.WriteLine(item.Key + " = " + item.Value);
    250                                 }
    251                                 //写入空行
    252                                 if (item.Key == "" && item.Description == "" && item.Value == "")
    253                                 {
    254                                     stream.WriteLine("");
    255                                 }
    256                             }
    257                         }
    258                         stream.Close();
    259                     }
    260                    
    261                    
    262                     isSave = true;
    263                 }
    264                 catch (Exception ex)
    265                 {
    266                     Debug.Print(ex.Message);
    267                 }
    268                 return isSave;
    269             }
    270 
    271             /// <summary>
    272             /// 内部类:Ini属性
    273             /// </summary>
    274             private class Property
    275             {
    276                 /// <summary>
    277                 /// 构造函数
    278                 /// </summary>
    279                 /// <param name="key"></param>
    280                 /// <param name="value"></param>
    281                 /// <param name="description"></param>
    282                 public Property(string key, string value, string description)
    283                 {
    284                     this.Key = key;
    285                     this.Value = value;
    286                     this.Description = description;
    287                 }
    288                 string key = "";
    289                 /// <summary>
    290                 ///291                 /// </summary>
    292                 public string Key
    293                 {
    294                     get { return key; }
    295                     set { key = value; }
    296                 }
    297                 string value = "";
    298                 /// <summary>
    299                 /// 键值
    300                 /// </summary>
    301                 public string Value
    302                 {
    303                     get { return this.value; }
    304                     set { this.value = value; }
    305                 }
    306                 string description = "";
    307                 /// <summary>
    308                 /// 注释
    309                 /// </summary>
    310                 public string Description
    311                 {
    312                     get { return description; }
    313                     set { description = value; }
    314                 }
    315 
    316                 public bool NeedDelete { get; set; }
    317 
    318             
    319             }
    320             #endregion
    321         }

    改进的地方有以下几点:

    1.查询由ArrayList+循环改成用Dictionary + List 然后用Linq查询配置项

    2.保存加了异步和延时保存

    可能存在的问题:

    1.因为保加了延时,不知道会不会出现丢失的可能

    2.为了支持维语ini文件改成了unicode编码,对于系统默认的ANSI编码支持没有测试过

    总结项目中使用ini的配置不能搞的太复杂,太复杂的不能放在ini里做,还是要想别的办法。

  • 相关阅读:
    Java--泛型
    Java--文档注释
    Java--网络编程
    Java--序列化
    Java--多线程编程
    Java--ConcurrentHashMap原理分析
    HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别
    面向接口编程详解
    面向接口编程
    base64 数据加密
  • 原文地址:https://www.cnblogs.com/linkbiz/p/14146741.html
Copyright © 2020-2023  润新知