zoukankan      html  css  js  c++  java
  • 基于正则的INI读写工具类,支持加密解密

    看到这个标题,有人会问,现在都用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文件的所有内容,代码如下:

    class Program
       {
          static void Main(string[] args)
          {
             try
             {
                INIHelper helper = new INIHelper("config.ini");
                Console.WriteLine(helper.GetValueByName("DBName"));
                Console.WriteLine(helper.GetValueByName("UserName"));
                Console.WriteLine(helper.GetValueByName("PassWord"));
                Console.WriteLine(helper.GetValueByName("Version"));
             }
             catch (Exception ex)
             {
                Console.WriteLine(ex.Message);
             }
    
             Console.Read();
          }
       }

    输出结果如下:

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

    class Program
       {
          static void Main(string[] args)
          {
             try
             {
                INIHelper helper = new INIHelper();
                helper.LoadINI("config.ini");
                Console.WriteLine(helper.GetValueByName("DBName"));
                Console.WriteLine(helper.GetValueByName("UserName"));
                Console.WriteLine(helper.GetValueByName("PassWord"));
                Console.WriteLine(helper.GetValueByName("Version"));
             }
             catch (Exception ex)
             {
                Console.WriteLine(ex.Message);
             }
    
             Console.Read();
          }
       }

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

    class Program
       {
          static void Main(string[] args)
          {
             try
             {
                INIHelper helper = new INIHelper();
                helper.LoadINI("config.ini");
                helper.SetValueByName("PassWord", "root");
                helper.SaveINI();
             }
             catch (Exception ex)
             {
                Console.WriteLine(ex.Message);
             }
    
             Console.Read();
          }
       }

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

     二、揭开INIHelper神秘的面纱

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

          private string newLine = "
    ";  //换行符
          private string filePath = string.Empty; //文件名称
          private string fileContent = string.Empty; //文件内容
    
          public INIHelper() { }
          /// <summary>
          /// 有参构造方法,直接读取INI文件
          /// </summary>
          /// <param name="filePath"></param>
          public INIHelper(string filePath)
          {
             this.LoadINI(filePath);
          }
    
          /// <summary>
          /// 加载并读取INI文件
          /// </summary>
          /// <param name="fileName">文件路径</param>
          public void LoadINI(string filePath)
          {
             if (filePath.Trim().Length > 0)
             {
                this.filePath = filePath;
                ReadINIFile();
             }
             else
             {
                throw new Exception("Invalid file name!");
             }
          }

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

    /// <summary>
          /// 读取INI文件
          /// </summary>
          private void ReadINIFile()
          {
             if (File.Exists(this.filePath))
             {
                try
                {
                   using (StreamReader sr = new StreamReader(this.filePath))
                   {
                      this.fileContent = sr.ReadToEnd();
                      this.fileContent = EncryptionAndDecryption(fileContent); //解密
                      //如果文件内容为空或者没有换行符,则认为是无效的INI文件。
                      if (fileContent.Trim().Length <= 0 || !fileContent.Contains("
    "))
                      {
                         throw new Exception("Invalid ini file");
                      }
                      else
                      {
                         //保存文件默认换行符
                         if (!fileContent.Contains(newLine))
                         {
                            this.newLine = "
    ";
                         }
                      }
                   }
                }
                catch (Exception ex)
                {
                   throw new Exception("Read file error! Error Message:" + ex.Message);
                }
             }
             else
             {
                throw new Exception("File " + filePath + " not found!");
             }
          }

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

    /// <summary>
          /// 读取INI文件某个配置项的值
          /// </summary>
          /// <param name="fieldName"></param>
          /// <returns></returns>
          public string GetValueByName(string fieldName)
          {
             fileContent = fileContent.Replace(newLine, ";");
             fileContent = fileContent.Replace(" ", "");
             fileContent = fileContent.EndsWith(";") ? fileContent : fileContent + ";";
             Regex reg = new Regex("(?<=" + fieldName + "=).*?(?=;)");
             Match m = reg.Match(fileContent);
             return m.Value;
          }
    
          /// <summary>
          /// 修改INI文件某个配置项的值
          /// </summary>
          /// <param name="fieldName"></param>
          /// <param name="value"></param>
          public void SetValueByName(string fieldName, string value)
          {
             string reg = "(?<=" + fieldName + "=).*?(?=;)";
             fileContent = Regex.Replace(fileContent, reg, value);
          }

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

    /// <summary>
          /// 保存对INI文件的修改
          /// </summary>
          public void SaveINI()
          {
             try
             {
                fileContent = fileContent.Replace(";", newLine); //替换换行符
                fileContent = EncryptionAndDecryption(fileContent); //加密
                using (StreamWriter sw = new StreamWriter(filePath))
                {
                   sw.Write(fileContent);
                   sw.Close();
                }
             }
             catch (Exception ex)
             {
                throw new Exception("Save file error! Error Message:" + ex.Message);
             }
          }
    
          /// <summary>
          /// 加密解密算法,使用异或算法
          /// </summary>
          /// <param name="str"></param>
          public string EncryptionAndDecryption(string str)
          {
             byte key = 32;
             byte[] buffer = Encoding.Default.GetBytes(str);
             for (int i = 0; i < buffer.Length; i++)
             {
                buffer[i] ^= key;
             }
             return Encoding.Default.GetString(buffer);
          }

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

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

    源码下载

  • 相关阅读:
    centos 安装nginx + 多个tomcat负载均衡
    centos 安装redis2.8.9
    centos下彻底删除mysql
    List的深度序列化Demo
    session失效刷新后登录页面嵌入在iframe中的解决办法
    Unable to execute dex: Multiple dex files define 解决方法
    Android运行时异常“Binary XML file line # : Error inflating class”
    在Android library中不能使用switch-case语句访问资源ID的原因分析及解决方案
    ViewStub的使用示例
    android中导入低版本project可能会遇到的编译问题
  • 原文地址:https://www.cnblogs.com/yunfeifei/p/4081977.html
Copyright © 2011-2022 走看看