C# 操作ini文件

INI文件是一种按照特点方式排列的文本文件。每一个INI文件构成都非常类似,由若干段落(section)组成,在每个带括号的标题下面,是若干个以单个单词开头的关键词(keyword)和一个等号,等

号右边的就是关键字对应的值(value)。其一般形式如下:

1 [section1]
2  keyword1=value1 
3  keyword2=value2
4  keyword3=value3
5 [section2]
6  keyword1=value1
7  keyword2=value2
 1 class Program
 2 
 3     {
 4 
 5         [DllImport("kernel32")]
 6 
 7         private  static extern long WritePrivateProfileString (string section ,string key , string val ,string filepath);
 8 
 9         //参数说明:section:INI文件中的段落;key:INI文件中的关键字;val:INI文件中关键字的数值;filePath:INI文件的完整的路径和名称。
10 
11         [DllImport ("kernel32")]
12 
13         private static extern int GetPrivateProfileString (string section , string key , string def , StringBuilder retVal , int size , string filePath ) ;
14 
15         //参数说明:section:INI文件中的段落名称;key:INI文件中的关键字;def:无法读取时候时候的缺省数值;retVal:读取数值;size:数值的大小;filePath:INI文件的完整路径和名称。
16 
17         public static void Main(string[] args)
18 
19         {
20 
21             
22 
23             string section="database";
24 
25             string key="sql";
26 
27             //string value="server.;database=pubs;uid=sa;pwd=";
28 
29             string fileName="d:\\config.ini";
30 
31             
32 
33             try
34 
35             {
36 
37                 //写入ini节点
38 
39                 //WritePrivateProfileString(section,key,value,fileName);
40 
41                 
42 
43                 //读取ini节点
44 
45                 StringBuilder sb=new StringBuilder(255);
46 
47                 GetPrivateProfileString(section,key,"无法读取",sb,255,fileName);
48 
49                 
50 
51                 Console.WriteLine(sb.ToString());
52 
53                 
54 
55             }catch(Exception ex)
56 
57             {
58 
59                 Console.WriteLine(ex.ToString());
60 
61             }
62 
63             
64 
65             Console.Write("Press any key to continue . . . ");
66 
67             Console.ReadKey(true);
68 
69         }
70 
71         
72 
73     }

整理出ini文件操作类:

  1 /// <summary>
  2     /// 读写INI文件的类。
  3     /// </summary>
  4     public class INIHelper
  5     {
  6         // 读写INI文件相关。
  7         [DllImport("kernel32.dll", EntryPoint = "WritePrivateProfileString", CharSet = CharSet.Ansi)]
  8         public static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
  9         [DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileString", CharSet = CharSet.Ansi)]
 10         public static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
 11 
 12         [DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileSectionNames", CharSet = CharSet.Ansi)]
 13         public static extern int GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer, int nSize, string filePath);
 14         
 15         [DllImport("KERNEL32.DLL ", EntryPoint = "GetPrivateProfileSection", CharSet = CharSet.Ansi)]
 16         public static extern int GetPrivateProfileSection(string lpAppName, byte[] lpReturnedString, int nSize, string filePath);
 17 
 18 
 19         /// <summary>
 20         /// 向INI写入数据。
 21         /// </summary>
 22         /// <PARAM name="Section">节点名。</PARAM>
 23         /// <PARAM name="Key">键名。</PARAM>
 24         /// <PARAM name="Value">值名。</PARAM>
 25         public static void Write(string Section, string Key, string Value, string path)
 26         {
 27             WritePrivateProfileString(Section, Key, Value, path);
 28         }
 29 
 30 
 31         /// <summary>
 32         /// 读取INI数据。
 33         /// </summary>
 34         /// <PARAM name="Section">节点名。</PARAM>
 35         /// <PARAM name="Key">键名。</PARAM>
 36         /// <PARAM name="Path">值名。</PARAM>
 37         /// <returns>相应的值。</returns>
 38         public static string Read(string Section, string Key, string path)
 39         {
 40             StringBuilder temp = new StringBuilder(255);
 41             int i = GetPrivateProfileString(Section, Key, "", temp, 255, path);
 42             return temp.ToString();
 43         }
 44 
 45         /// <summary>
 46         /// 读取一个ini里面所有的节
 47         /// </summary>
 48         /// <param name="sections"></param>
 49         /// <param name="path"></param>
 50         /// <returns></returns>
 51         public static int GetAllSectionNames(out string[] sections, string path)
 52         {
 53             int MAX_BUFFER = 32767;
 54             IntPtr pReturnedString = Marshal.AllocCoTaskMem(MAX_BUFFER);
 55             int bytesReturned = GetPrivateProfileSectionNames(pReturnedString, MAX_BUFFER, path);
 56             if (bytesReturned == 0)
 57             {
 58                 sections = null;
 59                 return -1;
 60             }
 61             string local = Marshal.PtrToStringAnsi(pReturnedString, (int)bytesReturned).ToString();
 62             Marshal.FreeCoTaskMem(pReturnedString);
 63             //use of Substring below removes terminating null for split
 64             sections = local.Substring(0, local.Length - 1).Split('\0');
 65             return 0;
 66         }
 67 
 68         /// <summary>
 69         /// 得到某个节点下面所有的key和value组合
 70         /// </summary>
 71         /// <param name="section"></param>
 72         /// <param name="keys"></param>
 73         /// <param name="values"></param>
 74         /// <param name="path"></param>
 75         /// <returns></returns>
 76         public static int GetAllKeyValues(string section, out string[] keys, out string[] values, string path)
 77         {
 78             byte[] b = new byte[65535];
 79 
 80             GetPrivateProfileSection(section, b, b.Length, path);
 81             string s = System.Text.Encoding.Default.GetString(b);
 82             string[] tmp = s.Split((char)0);
 83             ArrayList result = new ArrayList();
 84             foreach (string r in tmp)
 85             {
 86                 if (r != string.Empty)
 87                     result.Add(r);
 88             }
 89             keys = new string[result.Count];
 90             values = new string[result.Count];
 91             for (int i = 0; i < result.Count; i++)
 92             {
 93                 string[] item = result[i].ToString().Split(new char[] { '=' });
 94                 if (item.Length == 2)
 95                 {
 96                     keys[i] = item[0].Trim();
 97                     values[i] = item[1].Trim();
 98                 }
 99                 else if (item.Length == 1)
100                 {
101                     keys[i] = item[0].Trim();
102                     values[i] = "";
103                 }
104                 else if (item.Length == 0)
105                 {
106                     keys[i] = "";
107                     values[i] = "";
108                 }
109             }
110 
111             return 0;
112         }
113 
114     }

文件由若干个段落(section)组成,每个段落又分成若干个键(key)和值(value)。Windows系统自带的Win32的API函数GetPrivateProfileString()和WritePrivateProfileString()分别实现了对INI文件的读写操作,他们位于kernel32.dll下。

但是令人遗憾的是C#所使用的.NET框架下的公共类库并没有提供直接操作INI文件的类,所以唯一比较理想的方法就是调用API函数。

然后,.Net框架下的类库是基于托管代码的,而API函数是基于非托管代码的,(在运行库的控制下执行的代码称作托管代码。相反,在运行库之外运行的代码称作非托管代码。)如何实现托管代码与非托管代码之间的操作呢?.Net框架的System.Runtime.InteropServices命名空间下提供各种各样支持COM interop及平台调用服务的成员,其中最重要的属性之一DllImportAttribute可以用来定义用于访问非托管API的平台调用方法,它提供了对从非托管DLL导出的函数进行调用所必需的信息。下面就来看一下如何实现C#与API函数的互操作。

读操作:

1 [DllImport("kernel32")]
2 private static extern int GetPrivateProfileString(string section, string key, string defVal, StringBuilder retVal, int size, string filePath); 
3 section:要读取的段落名
4 key: 要读取的键
5 defVal: 读取异常的情况下的缺省值
6 retVal: key所对应的值,如果该key不存在则返回空值
7 size: 值允许的大小
8 filePath: INI文件的完整路径和文件名

写操作:

1 [DllImport("kernel32")] 
2 private static extern long WritePrivateProfileString(string section, string key, string val, string filePath); 
3 section: 要写入的段落名
4 key: 要写入的键,如果该key存在则覆盖写入
5 val: key所对应的值
6 filePath: INI文件的完整路径和文件名

这样,在就可以使用对他们的调用,用常规的方式定义一个名为IniFile类:

1using System;
 2using System.Runtime.InteropServices; 
 3using System.Text; 
 4
 5namespace IPVOD.Hotel.Remoting
 6{
 7    /// <summary>
 8    /// INI文件的操作类
 9    /// </summary>
10    public class IniFile
11    {
12        public string Path;
13
14        public IniFile(string path)
15        {
16            this.Path = path;
17        }
18        
19        #region 声明读写INI文件的API函数 
20        [DllImport("kernel32")] 
21        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath); 
22
23        [DllImport("kernel32")]
24        private static extern int GetPrivateProfileString(string section, string key, string defVal, StringBuilder retVal, int size, string filePath); 
25
26        [DllImport("kernel32")]
27        private static extern int GetPrivateProfileString(string section, string key, string defVal, Byte[] retVal, int size, string filePath);
28        #endregion
29
30        /// <summary>
31        /// 写INI文件
32        /// </summary>
33        /// <param name="section">段落</param>
34        /// <param name="key"></param>
35        /// <param name="iValue"></param>
36        public void IniWriteValue(string section, string key, string iValue) 
37        {
38            WritePrivateProfileString(section, key, iValue, this.Path);
39        }
40
41        /// <summary>
42        /// 读取INI文件
43        /// </summary>
44        /// <param name="section">段落</param>
45        /// <param name="key"></param>
46        /// <returns>返回的键值</returns>
47        public string IniReadValue(string section, string key) 
48        { 
49            StringBuilder temp = new StringBuilder(255); 
50
51            int i = GetPrivateProfileString(section, key, "", temp, 255, this.Path); 
52            return temp.ToString();
53        }
54
55        /// <summary>
56        /// 读取INI文件
57        /// </summary>
58        /// <param name="Section">段,格式[]</param>
59        /// <param name="Key"></param>
60        /// <returns>返回byte类型的section组或键值组</returns>
61        public byte[] IniReadValues(string section, string key)
62        {
63            byte[] temp = new byte[255];
64
65            int i = GetPrivateProfileString(section, key, "", temp, 255, this.Path);
66            return temp;
67        }
68    }
69}
70

注意:我增加了DLL导出的函数GetPrivateProfileString的重载,说明如下:

1 [DllImport("kernel32")] 
2 private static extern int GetPrivateProfileString(string section, string key, string defVal, Byte[] retVal, int size, string filePath);
3 section:要读取的段落名
4 key: 要读取的键
5 defVal: 读取异常的情况下的缺省值
6 retVal: 此参数类型不是string,而是Byte[]用于返回byte类型的section组或键值组。
7 size: 值允许的大小
8 filePath: INI文件的完整路径和文件名
 1 下面看一下具体实例化IniFile类的操作:
 2 
 3 //path为ini文件的物理路径
 4 
 5 IniFile ini = new IniFile(path);
 6 
 7 //读取ini文件的所有段落名
 8 
 9 byte[] allSection = ini.IniReadValues(null, null);
10 
11  
12 
13 通过如下方式转换byte[]类型为string[]数组类型
14 
15 string[] sectionList;
16 
17 ASCIIEncoding ascii = new ASCIIEncoding();
18 
19 //获取自定义设置section中的所有key,byte[]类型
20 
21 sectionByte = ini.IniReadValues("personal", null);
22 
23 //编码所有key的string类型
24 
25 sections = ascii.GetString(sectionByte);
26 
27 //获取key的数组
28 
29 sectionList = sections.Split(new char[1]{'\0'});
30 
31  
32 
33 //读取ini文件personal段落的所有键名,返回byte[]类型
34 
35 byte[] sectionByte = ini.IniReadValues("personal", null);
36 
37  
38 
39 //读取ini文件evideo段落的MODEL键值
40 
41 model = ini.IniReadValue("evideo", "MODEL");
42 
43  
44 
45 //将值eth0写入ini文件evideo段落的DEVICE键
46 
47 ini.IniWriteValue("evideo", "DEVICE", "eth0");
48 
49 即:
50 
51 [evideo]
52 
53 DEVICE = eth0
54 
55  
56 
57 //删除ini文件下personal段落下的所有键
58 
59 ini.IniWriteValue("personal", null, null);
60 
61  
62 
63 //删除ini文件下所有段落
64 
65 ini.IniWriteValue(null, null, null);

创建Ini参考:http://blog.csdn.net/sdfkfkd/article/details/7050733

posted @ 2013-10-20 22:07  酣睡的熊㊣  阅读(510)  评论(0编辑  收藏  举报