看到这个标题,有人会问,现在都用xml做配置文件了,谁还用INI文件啊!下面来简单对比一下xml和ini:

  1、XML功能强大表达能力强,同时扩展性好。
  2、它的主要优势是异构平台的整合、通讯。
  3、缺点主要是使用复杂,运行库占用的资源较多。
  4、如果多个程序进行数据交换或是跨平台通讯则使用功能强大的XML;

  5、INI虽表达能力不强,但是简单实用,接口方便。如果是用于应用程序的配置INI文件就够了。

至于哪个更好,应该用哪个,可以根据自己爱好和需求。个人感觉INI文件操作简单,就是读取文件,处理字符串,保存到文件,可谓是简单粗暴。而且内容也比较友好,没有冗余的东西。

  由于最近项目中用到INI文件,所以抽空编写了一个Helper,取名交INIHelper。这里先不给出它的源码,先来看下他的用法。

 一、INIHelper的用法

  这里为了做演示,我建了一个C# 控制台应用程序,随便起了个名字,加入了INIHelper这个类。项目结构如图:

在Debug目录下面添加了一个config.ini的文件,内容如下:

下面我们用这个Helper来读取这个INI文件的所有内容,代码如下:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. try
  6. {
  7. INIHelper helper = new INIHelper("config.ini");
  8. Console.WriteLine(helper.GetValueByName("DBName"));
  9. Console.WriteLine(helper.GetValueByName("UserName"));
  10. Console.WriteLine(helper.GetValueByName("PassWord"));
  11. Console.WriteLine(helper.GetValueByName("Version"));
  12. }
  13. catch (Exception ex)
  14. {
  15. Console.WriteLine(ex.Message);
  16. }
  17.  
  18. Console.Read();
  19. }
  20. }

输出结果如下:

是不是很方便,这里还有另外一种写法,代码如下:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. try
  6. {
  7. INIHelper helper = new INIHelper();
  8. helper.LoadINI("config.ini");
  9. Console.WriteLine(helper.GetValueByName("DBName"));
  10. Console.WriteLine(helper.GetValueByName("UserName"));
  11. Console.WriteLine(helper.GetValueByName("PassWord"));
  12. Console.WriteLine(helper.GetValueByName("Version"));
  13. }
  14. catch (Exception ex)
  15. {
  16. Console.WriteLine(ex.Message);
  17. }
  18.  
  19. Console.Read();
  20. }
  21. }

代码中加粗的部分就是另外一种写法,一种方法是在构造时加载ini文件,另外一种方法时在需要的时候加载。到这里读取ini文件的就说完了,下面来说一下修改ini文件。这里我们来修改ini文件密码为root,然后保存到ini文件中,来看看代码怎么写:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. try
  6. {
  7. INIHelper helper = new INIHelper();
  8. helper.LoadINI("config.ini");
  9. helper.SetValueByName("PassWord", "root");
  10. helper.SaveINI();
  11. }
  12. catch (Exception ex)
  13. {
  14. Console.WriteLine(ex.Message);
  15. }
  16.  
  17. Console.Read();
  18. }
  19. }

首先加载ini文件,然后调用SetValueByName方法修改密码,最后调用SaveINI方法保存。保存后,可以打开ini文件看到内容变了,这里就不再截图了。其还支持加密解密,这样我们的配置文件内容就不会被被人看到和随意修改了,加密后的效果如下:

 二、揭开INIHelper神秘的面纱

  下面来看看INIHelper的具体实现,首先来看构造方法和LoadINI,其实现代码如下:

  1. private string newLine = "\r\n"; //换行符
  2. private string filePath = string.Empty; //文件名称
  3. private string fileContent = string.Empty; //文件内容
  4.  
  5. public INIHelper() { }
  6. /// <summary>
  7. /// 有参构造方法,直接读取INI文件
  8. /// </summary>
  9. /// <param name="filePath"></param>
  10. public INIHelper(string filePath)
  11. {
  12. this.LoadINI(filePath);
  13. }
  14.  
  15. /// <summary>
  16. /// 加载并读取INI文件
  17. /// </summary>
  18. /// <param name="fileName">文件路径</param>
  19. public void LoadINI(string filePath)
  20. {
  21. if (filePath.Trim().Length > )
  22. {
  23. this.filePath = filePath;
  24. ReadINIFile();
  25. }
  26. else
  27. {
  28. throw new Exception("Invalid file name!");
  29. }
  30. }

可以看到在有参构造方法里面调用了LoadINI方法,所以等价于调用无参构造函数然后调用LoadINI方法。LoadINI方法里面首先判断文件路径是否合法,合法的话就读取ini文件,否则抛出异常。ReadINIFile方法就是读取文件内容,然后赋给fileContent,其实现如下:

  1. /// <summary>
  2. /// 读取INI文件
  3. /// </summary>
  4. private void ReadINIFile()
  5. {
  6. if (File.Exists(this.filePath))
  7. {
  8. try
  9. {
  10. using (StreamReader sr = new StreamReader(this.filePath))
  11. {
  12. this.fileContent = sr.ReadToEnd();
  13. this.fileContent = EncryptionAndDecryption(fileContent); //解密
  14. //如果文件内容为空或者没有换行符,则认为是无效的INI文件。
  15. if (fileContent.Trim().Length <= || !fileContent.Contains("\n"))
  16. {
  17. throw new Exception("Invalid ini file");
  18. }
  19. else
  20. {
  21. //保存文件默认换行符
  22. if (!fileContent.Contains(newLine))
  23. {
  24. this.newLine = "\n";
  25. }
  26. }
  27. }
  28. }
  29. catch (Exception ex)
  30. {
  31. throw new Exception("Read file error! Error Message:" + ex.Message);
  32. }
  33. }
  34. else
  35. {
  36. throw new Exception("File " + filePath + " not found!");
  37. }
  38. }

这个已经包含了加密解密的方法,首先读取文件内容,解密,然后判断文件是否合法,及是否有为空和是否有换行符,然后判断里面的换行符是否为默认值,否则修改newLine为文件默认的换行符。(大家可以修改代码,自定分割符。默认是支持\r\n或\n)

  1. /// <summary>
  2. /// 读取INI文件某个配置项的值
  3. /// </summary>
  4. /// <param name="fieldName"></param>
  5. /// <returns></returns>
  6. public string GetValueByName(string fieldName)
  7. {
  8. fileContent = fileContent.Replace(newLine, ";");
  9. fileContent = fileContent.Replace(" ", "");
  10. fileContent = fileContent.EndsWith(";") ? fileContent : fileContent + ";";
  11. Regex reg = new Regex("(?<=" + fieldName + "=).*?(?=;)");
  12. Match m = reg.Match(fileContent);
  13. return m.Value;
  14. }
  15.  
  16. /// <summary>
  17. /// 修改INI文件某个配置项的值
  18. /// </summary>
  19. /// <param name="fieldName"></param>
  20. /// <param name="value"></param>
  21. public void SetValueByName(string fieldName, string value)
  22. {
  23. string reg = "(?<=" + fieldName + "=).*?(?=;)";
  24. fileContent = Regex.Replace(fileContent, reg, value);
  25. }

这个是读取和修改某个配置项的方法,使用正则表达式进行匹配。修改只是修改fileContent的值,并不执行保存。

  1. /// <summary>
  2. /// 保存对INI文件的修改
  3. /// </summary>
  4. public void SaveINI()
  5. {
  6. try
  7. {
  8. fileContent = fileContent.Replace(";", newLine); //替换换行符
  9. fileContent = EncryptionAndDecryption(fileContent); //加密
  10. using (StreamWriter sw = new StreamWriter(filePath))
  11. {
  12. sw.Write(fileContent);
  13. sw.Close();
  14. }
  15. }
  16. catch (Exception ex)
  17. {
  18. throw new Exception("Save file error! Error Message:" + ex.Message);
  19. }
  20. }
  21.  
  22. /// <summary>
  23. /// 加密解密算法,使用异或算法
  24. /// </summary>
  25. /// <param name="str"></param>
  26. public string EncryptionAndDecryption(string str)
  27. {
  28. byte key = ;
  29. byte[] buffer = Encoding.Default.GetBytes(str);
  30. for (int i = ; i < buffer.Length; i++)
  31. {
  32. buffer[i] ^= key;
  33. }
  34. return Encoding.Default.GetString(buffer);
  35. }

SaveINI执行加密后保存到ini文件,这里给出了简单的对称加密算法,大家使用时可以使用自定义的加密算法。

注意:笫一次读取配置文件由于没有加密,调用了解密算法,所以会出现文件无效的异常。这里需要先加密保存一次,然后就好了。

源码下载

基于正则的INI读写工具类,支持加密解密的更多相关文章

  1. 适用于app.config与web.config的ConfigUtil读写工具类 基于MongoDb官方C#驱动封装MongoDbCsharpHelper类(CRUD类) 基于ASP.NET WEB API实现分布式数据访问中间层(提供对数据库的CRUD) C# 实现AOP 的几种常见方式

    适用于app.config与web.config的ConfigUtil读写工具类   之前文章:<两种读写配置文件的方案(app.config与web.config通用)>,现在重新整理一 ...

  2. 基于JavaMail开发邮件发送器工具类

    基于JavaMail开发邮件发送器工具类 在开发当中肯定会碰到利用Java调用邮件服务器的服务发送邮件的情况,比如账号激活.找回密码等功能.本人之前也碰到多次这样需求,为此特意将功能封装成一个简单易用 ...

  3. Android开发调试日志工具类[支持保存到SD卡]

    直接上代码: package com.example.callstatus; import java.io.File; import java.io.FileWriter; import java.i ...

  4. properties文件读写工具类

    java代码: import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; ...

  5. Spring-Boot ☞ ShapeFile文件读写工具类+接口调用

    一.项目目录结构树 二.项目启动 三.往指定的shp文件里写内容 (1) json数据[Post] { "name":"test", "path&qu ...

  6. android 文件读写工具类

    将可以序列化的对象通过base64编码后进行保存 但是感觉多数情况下,不需要采用这个功能,直接保存原始的json字符串,取出来之后再进行解析即可 package com.wotlab.home.mon ...

  7. java文件读写工具类

    依赖jar:commons-io.jar 1.写文件 // by FileUtilsList<String> lines = FileUtils.readLines(file, " ...

  8. 适用于app.config与web.config的ConfigUtil读写工具类

    之前文章:<两种读写配置文件的方案(app.config与web.config通用)>,现在重新整理一个更完善的版本,增加批量读写以及指定配置文件路径,代码如下: using System ...

  9. 基于JavaScript封装的Ajax工具类

    前段是件由于工作需要无奈编写了一个给予JavaScript封装的工具类,技术有限,误喷,感谢大家的支持. 1.以下是JavaScript 的 Ajax 工具类. function createXMLH ...

随机推荐

  1. ViewPager循环显示

    好久没有写博客了,今天加一个ViewPager页面的循环显示,添加了一个删除页面的小按钮: MainActivity.java package com.yt.viewpagerlooper; impo ...

  2. android开发学习笔记000

    使用书籍:<疯狂android讲义>——李刚著,2011年7月出版 虽然现在已2014,可我挑来跳去,还是以这本书开始我的android之旅吧. “疯狂源自梦想,技术成就辉煌.” 让我这个 ...

  3. Crystal Reports拉报表报错:Error detected by database DLL

    问题描述: 最近在使用Crystal Reports打印报表时,提示错误信息:"Error detected by database DLL." 如下图: 经查找,是因为数据库名称 ...

  4. javascript里的继承

    js里面继承的方式, 1. 类式继承,通过构造函数的继承 function extend(subClass, superClass){ var F = function(){}; F.prototyp ...

  5. HtmlAgilityPack组件

    HtmlAgilityPack组件用于解析Html字符串,一个典型的应用场景是用于网页爬虫. 示例程序 using Common.Tools; using Datebase.Entity; using ...

  6. CodeForces 743A Vladik and flights (水题)

    题意:sb要从a到b,然后要乘坐飞机,只有两家有飞机,如果乘坐同一家的,就免费,如果不是就收到abs(j-i) 的费用,问你最少花费是多少. 析:直接考虑a和b是不是同一家的,如果是,花费为0,如果不 ...

  7. shell选择语句

    if语句 1) if ... else 语句 if ... else 语句的语法: if [ expression ] then Statement(s) to be executed if expr ...

  8. BZOJ1188 [HNOI2007]分裂游戏(SG函数)

    传送门 拿到这道题就知道是典型的博弈论,但是却不知道怎么设计它的SG函数.看了解析一类组合游戏这篇论文之后才知道这道题应该怎么做. 这道题需要奇特的模型转换.即把每一个石子当做一堆石子,且原来在第i堆 ...

  9. [RabbitMQ+Python入门经典] 兔子和兔子窝

    原文联接: http://blogs.digitar.com/jjww/2009/01/rabbits-and-warrens/ RabbitMQ作为一个工业级的消息队列服务器,在其客户端手册列表的P ...

  10. Java 后台获取当前时间

    Calendar c = Calendar.getInstance();//可以对每个时间域单独修改 int year = c.get(Calendar.YEAR); int month = c.ge ...