原创 C# 正则表达式 读写 Ini 文件

昨天遇到读ini文件的问题,我知道C#里没有提供相应的类,所有的.net配置都是xml方式存储的。

读取ini文件,很多人直接google一把,然后添加dll引用。介绍的比较详细的,如: C#如何读写和创建INI文件 

那么,如果不引用api呢? 我想到了正则表达式,分别读取section与key value,然后再匹配。刚好网上有一个类似的文章 用正则表达式读取INI文件

看了下他的内容,然后再整理下思路,OK,我自己的Helper就出来了

namespace goldli.Utility.Library
{
    public interface IPosition
    {
        int Position { get; set; }     
    }

    public class IniKey : IPosition
    {
        public string Name { get; set; }

        public string Value { get; set; }

        public int Position { get; set; }
    }

    public class IniSection : Collection<IniKey>, IPosition
    {
        /// <summary>
        /// Section名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// section在文件里位置,用于与KeyValue对比
        /// </summary>
        public int Position { get; set; }

        public IniKey Add(string keyName)
        {
            var result = Find(keyName);
            if (result == null)
            {
                var key = new IniKey{Name = keyName};
                Add(key);
            }
            return result;
        }

        public void Remove(string keyName)
        {
            var key = Find(keyName);
            if (key == null) return;
            Remove(key);
        }

        public override IniKey Find(object value)
        {
            var keyName = value as string;
            if(string.IsNullOrEmpty(keyName)) throw new ArgumentNullException("value");
            IniKey result = null;
            Lock();
            foreach (IniKey key in List)
            {
                if (!Tools.IsSameString(key.Name, keyName)) continue;
                result = key;
                break;
            }
            UnLock();
            return result;
        }

        /// <summary>
        /// 判断一个key是否存在
        /// </summary>
        /// <param name="keyName"></param>
        /// <returns></returns>
        public bool KeyIsExist(string keyName)
        {
            return Find(keyName) != null;
        }

        /// <summary>
        /// 读取一个值
        /// </summary>
        /// <param name="keyName"></param>
        /// <returns></returns>
        public string ReadValue(string keyName)
        {
            var key = Find(keyName);
            return key != null ? key.Value : null;
        }

        /// <summary>
        /// 写入一个值
        /// </summary>
        /// <param name="keyName"></param>
        /// <param name="value"></param>
        public void WriteValue(string keyName,string value)
        {
            Add(keyName).Value = value;
        }
    }

    public class Sections :Collection<IniSection>
    {
        /// <summary>
        /// 查找
        /// </summary>
        /// <param name="value">Section.Name</param>
        /// <returns></returns>
        public override IniSection Find(object value)
        {
            var sectionName = value as string;
            if (string.IsNullOrEmpty(sectionName)) throw new ArgumentNullException("value");
            IniSection result = null;
            Lock();
            foreach (IniSection section in List)
            {
                if (!Tools.IsSameString(section.Name,sectionName)) continue;
                result = section;
                break;
            }
            UnLock();
            return result;
        }
    }

    /// <summary>
    /// Ini文件读写类
    /// </summary>
    public class IniHelper
    {
        private IniKey[] _array;
        private int _arrarIndex;

        private const string ExpSection = "(?<=\\[)\\w+(?=\\]\\r)";

        /// <summary>
        /// 注:你要保证键值对中值不为空,即使是空字符串也不行
        /// </summary>
        private const string ExpKeyValue = "^(?<key>(?!;).+?)\\s*=\\s*(?<value>.*(?=\\r))";

        //ini文件
        private readonly string _fileName;

        private void ExtractKeyValues(string data)
        {
            try
            {
                var regexObj = new Regex(ExpKeyValue, RegexOptions.Multiline);
                var mc = regexObj.Matches(data);
                if (mc.Count > 0)
                {
                    _array = new IniKey[mc.Count];
                    for (var i = 0; i < mc.Count; i++)
                    {
                        var m = mc[i].Groups;
                        var key = new IniKey { Name = m[1].Value, Value = m[2].Value, Position = m[1].Index };
                        _array[i] = key;
                    }
                }
                else
                {
                    throw new RankException("error when regex key values.");
                }
            }
            catch (Exception ex)
            {
                Sections.Clear();
                throw;
            }
        }

        private void ExtractSections(string data)
        {
            try
            {
                var regexObj = new Regex(ExpSection);
                var matchResults = regexObj.Match(data);
                while (matchResults.Success)
                {
                    var g = matchResults.Groups[0];
                    var section = new IniSection { Name = g.Value, Position = g.Index };
                    Sections.Add(section);
                    matchResults = matchResults.NextMatch();
                }
            }
            catch (Exception ex)
            {
                Sections.Clear();
                throw;
            }
        }

        /// <summary>
        /// 根据起始位置查找keyvalue
        /// </summary>
        /// <param name="section"></param>
        /// <param name="next"></param>
        private void FillSection(IniSection section,int next)
        {
            for (var i = _arrarIndex; i < _array.Length; i++)
            {
                var key = _array[i];
                if ((section.Position < key.Position) && (key.Position < next))
                {
                    section.Add(key);
                    _arrarIndex++;
                }
                else
                    break;
            }
        }

        private void FillSections()
        {
            _arrarIndex = 0;
            for (var i = 0; i < Sections.Count; i++)
            {
                var section = Sections[i];
                var next = int.MaxValue;
                if ((i + 1) != Sections.Count)
                    next = Sections[i + 1].Position;
                FillSection(section,next);
            }
            Array.Clear(_array,0,_array.Length);
        }

        public IniHelper(string fileName)
        {
            _fileName = fileName;
            Sections =new Sections();
        }

        /// <summary>
        /// 文件编码
        /// </summary>
        public Encoding FileEncoding { get; set; }

        /// <summary>
        /// 加载文件
        /// </summary>
        public void Load()
        {
            var data = FileReadWriteHelper.Read(_fileName, FileEncoding.WebName);
            if (string.IsNullOrEmpty(data)) throw new FileLoadException(_fileName);
            ExtractSections(data);
            ExtractKeyValues(data);
            FillSections();
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        public void Save(string fileName)
        {
            var iniBuilder = new StringBuilder();
            foreach (IniSection section in Sections)
            {
                var aSection = string.Format("[{0}]\r\n", section.Name);
                iniBuilder.Append(aSection);
                foreach (IniKey key in section)
                {
                    var aKeyValue = string.Format("{0}={1}\r\n", key.Name, key.Value);
                    iniBuilder.Append(aKeyValue);
                }
                iniBuilder.Append(Environment.NewLine);
            }
            FileReadWriteHelper.Write(fileName, iniBuilder.ToString(), FileEncoding.WebName);
        }

        public IniSection Add(string sectionName)
        {
            var section = Sections.Find(sectionName);
            if (section == null)
            {
                section = new IniSection {Name = sectionName};
                Sections.Add(section);
            }
            return section;
        }

        public void Add(IniSection section)
        {
            var tmp = Sections.Find(section.Name);    
            if (tmp == null) 
                Sections.Add(section);
        }

        public void Remove(string sectionName)
        {
            var section = Sections.Find(sectionName);
            if (section == null) return;
            Sections.Remove(section);
        }

        public void Remove(IniSection section)
        {
            var tmp = Sections.Find(section.Name);
            if (tmp == null) return;
            Sections.Remove(section);
        }

        public Sections Sections { get; private set; }
    }
}

 使用示例

  var ini = new IniHelper(@"i:\spring.ini");
  ini.FileEncoding = Encoding.ASCII;
  ini.Load();
  textBox1.Clear();
  foreach (IniSection section in ini.Sections)
  {
      extBox1.AppendText("[" + section.Name +"]\r\n");
      foreach (IniKey key in section)
      {
          textBox1.AppendText(key.Name + " = " + key.Value + "\r\n");    
      }
  }

 哈哈,其实挺简单的。主要的问题是把正则写正确。

posted @ 2013-07-11 11:15  (大贤者模式)  阅读(913)  评论(0编辑  收藏  举报