昨天遇到读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. javaweb学习总结(三十九)——数据库连接池

    一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...

  2. MSSQL版本

    (1)661是sql2008 R2的版本号     Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (Intel X86)   Apr  2 201 ...

  3. SPRING IN ACTION 第4版笔记-第五章BUILDING SPRING WEB APPLICATIONS-005-以path parameters的形式给action传参数(value=“{}”、@PathVariable)

    一 1.以path parameters的形式给action传参数 @Test public void testSpittle() throws Exception { Spittle expecte ...

  4. C#中的异常处理

    C#中的异常处理 while (ex != null) { WriteExceptionLog(ex, fileName); ex = ex.InnerException; } /// <sum ...

  5. URAL1029. Ministry(DP+路径)

    链接 路径麻烦啊 很多细节 倒回去搜一遍 卡了一节数据库.. #include <iostream> #include<cstdio> #include<cstring& ...

  6. Oracle Java SE远程安全漏洞(CVE-2013-5878)

    漏洞版本: Oracle Java SE 7u45 Oracle Java SE 6u65 漏洞描述: BUGTRAQ ID: 64927 CVE(CAN) ID: CVE-2013-5878 Jav ...

  7. 为SharePoint网站创建自定义导航菜单

    转:http://kaneboy.blog.51cto.com/1308893/397779 相信不少人都希望把SharePoint网站内置的那个顶部导航菜单,换成自己希望的样式.由于SharePoi ...

  8. rfc all download

    http://www.rfc-editor.org/download.html about RTSP http://en.wikipedia.org/wiki/Real_Time_Streaming_ ...

  9. BZOJ2005: [Noi2010]能量采集 莫比乌斯反演的另一种方法——nlogn筛

    分析:http://www.cnblogs.com/huhuuu/archive/2011/11/25/2263803.html 注:从这个题收获了两点 1,第一象限(x,y)到(0,0)的线段上整点 ...

  10. selenium 处理浏览器多窗口

    测试过程中,会弹出一些子窗口,并且有可能在多个窗口之间切换 必须要获取每个窗口的唯一标识符切换到该窗口,才能对该窗口的元素进行操作 首先,获取每个窗口的唯一标识符,然后以及和的形式返回 var mai ...