昨天遇到读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");
}
}

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

原创 C# 正则表达式 读写 Ini 文件的更多相关文章

  1. c# 利用动态库DllImport("kernel32")读写ini文件(提供Dmo下载)

    c# 利用动态库DllImport("kernel32")读写ini文件 自从读了设计模式,真的会改变一个程序员的习惯.我觉得嘛,经验也可以从一个人的习惯看得出来,看他的代码编写习 ...

  2. VB读写INI文件的四个函数以及相关API详细说明

    WritePrivateProfileString函数说明  来源:http://blog.csdn.net/wjb9921/article/details/2005000 在我们写的程序当中,总有一 ...

  3. C# 读写INI 文件

    INI 格式: [Section1] KeyWord1 = Value1 KeyWord2 = Value2 ... [Section2] KeyWord3 = Value3 KeyWord4 = V ...

  4. WIN32读写INI文件方法

      在程序中经常要用到设置或者其他少量数据的存盘,以便程序在下一次执行的时候可以使用,比如说保存本次程序执行时窗口的位置.大小.一些用户设置的 数据等等,在 Dos 下编程的时候,我们一般自己产生一个 ...

  5. 读写ini文件

    C# 使用文件流来读写ini文件 背景 之前采用ini文件作为程序的配置文件,觉得这种结构简单明了,配置起来也挺方便.然后操作方式是通过WindowsAPI,然后再网上找到一个基于WindowsAPI ...

  6. 在 WinCe 平台读写 ini 文件

    在上篇文章开发 windows mobile 上的今日插件时,我发现 wince 平台上不支持例如 GetPrivateProfileString 等相关 API 函数.在网络上我并没有找到令我满意的 ...

  7. Windows中读写ini文件

    .ini 文件是Initialization File的缩写,即初始化文件,是windows的系统配置文件所采用的存储格式,来配置应用软件以实现不同用户的要求.配置文件有很多种如ini配置文件,XML ...

  8. C#中读写INI文件

    C#中读写INI文件 c#的类没有直接提供对ini文件的操作支持,可以自己包装win api的WritePrivateProfileString和GetPrivateProfileString函数实现 ...

  9. Qt读写ini文件

    一 背景 1 ini文件介绍 .ini 文件是Initialization File的缩写,即初始化文件. 除了windows现在很多其他操作系统下面的应用软件也有.ini文件,用来配置应用软件以实现 ...

  10. 【python-ini】python读写ini文件

    [python-ini]python读写ini文件 本文实例讲述了Python读写ini文件的方法.分享给大家供大家参考.具体如下: 比如有一个文件update.ini,里面有这些内容:   1 2 ...

随机推荐

  1. USB Type-C 应用面临安全性考验,USB-IF 将推动新认证机制

    USB 应用已经达到空前盛况,横跨电脑.移动设备.周边设备.影音器材等范畴,是一个极为普遍常见的界面.进入 USB Type-C 世代由于一并推动 USB-PD,过去没有严格执行的认证要求,基于安全性 ...

  2. make menuconfig出错

    make[1]: *** [scripts/kconfig/mconf] Error 1 make: *** [menuconfig] Error 2 fixed: sudo apt-get inst ...

  3. Mapreduce-Partition分析

    Partition所处的位置 Partition位置 Partition主要作用就是将map的结果发送到相应的reduce.这就对partition有两个要求: 1)均衡负载,尽量的将工作均匀的分配给 ...

  4. DedeCMS 5.7 config.php 跨站脚本漏洞

    漏洞版本: DedeCMS 5.7 漏洞描述: DeDeCMS v5.7 在/include/dialog/config.php文件中存在XSS漏洞,攻击者可以利用该漏洞盗取用户Cookie.挂马等. ...

  5. 纯CSS实现侧边栏/分栏高度自动相等

    by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=694 一.为何要分栏高 ...

  6. SharePoint 2010 Ribbon的实现

    转:http://blog.csdn.net/wang4237/article/details/5306335 SharePoint2010的页面风格发生了很大的改变,其页面风格类似于Office的视 ...

  7. Tomcat工作原理详解

    一.Tomcat背景 自从JSP发布之后,推出了各式各样的JSP引擎.Apache Group在完成GNUJSP1.0的开发以后,开始考虑在SUN的JSWDK基础上开发一个可以直接提供Web服务的JS ...

  8. SQL Server触发器以及如何在SQL Server Manager中调试触发器

    ·只有inserted表有数据时,当前操作为insert:·inserted和deleted两张表都有数据时,当前操作为update:·只有deleted表有数据时,当前操作为delete. 1. C ...

  9. Python:变量与字符串

    变量   使用dos页面进行命令的输入如下变量,进行打印: 同时,相同两个变量书写在同一行,中间用英文的“;”隔开 python中区分大小写变量 字符串   简单的说,字符串就是双引号,单引号,或者三 ...

  10. Windows下搭建Nginx实现负载均衡

    环境:本次测试,使用两台电脑,分别是 192.168.0.1,192.168.0.2. 其中Nginx也部署在 192.168.0.1 电脑上,所以 PC1 的IIS端口不能使用80,因为Nginx需 ...