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

时间:2023-03-08 20:28:18
原创 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");
}
}

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