背景
之前采用ini文件作为程序的配置文件,觉得这种结构简单明了,配置起来也挺方便。然后操作方式是通过WindowsAPI,然后再网上找到一个基于WindowsAPI封装的help类,用起来倒也顺手。用的多了,觉得还可以使用文件流来操作,后来就发现了EasyConfig。
EasyConfig是一个纯C#的开源ini文件操作库,但是在使用上有诸多不便,只是个人感觉,于是个人将其改造了一下,是自己喜欢用的风格。
资源下载
如果不清楚ini文件结构,请百度一下,这里贴一个示例文件。

[Video] #是否全屏 Fullscreen = true #宽度 Width = 1280 #电视高度 #高度 Height = 720 [Level1] NumberOfEnemies=2000#数值 Lives = 10 Timer = 999 EnemyNames = "Steve", "Sam", "Bill" EnemyGuns = 13, 28, 43, 499 CanShoot = true, yes, on, no, false, off
代码示例
首先来看看改写后,怎么去使用她来读写Ini文件。
static void Main(string[] args)
{
ConfigFile configFile = new ConfigFile("Test.ini");
//遍历Config文件
foreach (var group in configFile.SettingGroups)
{
Console.WriteLine("****************************");
Console.WriteLine(group.Key + ":");
Console.WriteLine();
foreach (var value in group.Value.Settings)
Console.WriteLine("{0} = {1} (Is Array? {2}),{3}", value.Key, value.Value.RawValue, value.Value.IsArray, value.Value.Desp);
Console.WriteLine();
}
//读取值主要是在具体的配置项上进行读取,是首先定位到[Group],其次就是具体的项
//使用泛型读取值,并指定读取失败时的默认值
var fullScreen = configFile["Video"]["Fullscreen"].As<int>(-1);//失败
var bFullScreen = configFile["Video"]["Fullscreen"].AsBool();//成功
var arrCanShoot = configFile["Level1"]["CanShoot"].AsArray<bool>();
//读取时 该项不存在,不存在的组或者项会自动添加
var noexists = configFile["Video"]["xxxxxxxxxxx"].AsString();
var noexists2 = configFile["Video111111111"]["xxxxxxxxxxx"].AsString();
//写入值有2种方法,可以直接向某组下写入一项,也可以定位到某组某项,写入值
//写入值 该项不存在,组或者项会自动创建
configFile["Video"].WriteSetting("NewName", "EasyConfig");
configFile["Video"].WriteSetting("NewName", "EasyConfig2.0");
configFile["Video22222222"].WriteSetting("c1", "1");
//索引器不过是返回Setting
configFile["Video3333"]["UserName"].SetValue("admin");
configFile["Viedo4444"]["Sex"].SetValue("男", "女", "保密");
//写入值,该项不存在
configFile["Video222"].WriteSetting("NewName", "EasyConfig3.0");
Console.ReadKey(true);
configFile.Save("TestConfig2.txt");
}
基本上自己想要的效果,则是基于 ConfigFile["GroupName"]["Key"] 这样的方式来进行读写。
另外附上一个基于WindowsAPI操作的封装类。

1 /// <summary>
2 /// Provides methods for reading and writing to an INI file.
3 /// </summary>
4 public class IniFileHelp
5 {
6 /// <summary>
7 /// The maximum size of a section in an ini file.
8 /// </summary>
9 /// <remarks>
10 /// This property defines the maximum size of the buffers
11 /// used to retreive data from an ini file. This value is
12 /// the maximum allowed by the win32 functions
13 /// GetPrivateProfileSectionNames() or
14 /// GetPrivateProfileString().
15 /// </remarks>
16 public const int MaxSectionSize = 32767; // 32 KB
17
18 //The path of the file we are operating on.
19 private string m_path;
20
21 #region P/Invoke declares
22
23 /// <summary>
24 /// A static class that provides the win32 P/Invoke signatures
25 /// used by this class.
26 /// </summary>
27 /// <remarks>
28 /// Note: In each of the declarations below, we explicitly set CharSet to
29 /// Auto. By default in C#, CharSet is set to Ansi, which reduces
30 /// performance on windows 2000 and above due to needing to convert strings
31 /// from Unicode (the native format for all .Net strings) to Ansi before
32 /// marshalling. Using Auto lets the marshaller select the Unicode version of
33 /// these functions when available.
34 /// </remarks>
35 [System.Security.SuppressUnmanagedCodeSecurity]
36 private static class NativeMethods
37 {
38 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
39 public static extern int GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer,
40 uint nSize,
41 string lpFileName);
42
43 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
44 public static extern uint GetPrivateProfileString(string lpAppName,
45 string lpKeyName,
46 string lpDefault,
47 StringBuilder lpReturnedString,
48 int nSize,
49 string lpFileName);
50
51 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
52 public static extern uint GetPrivateProfileString(string lpAppName,
53 string lpKeyName,
54 string lpDefault,
55 [In, Out] char[] lpReturnedString,
56 int nSize,
57 string lpFileName);
58
59 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
60 public static extern int GetPrivateProfileString(string lpAppName,
61 string lpKeyName,
62 string lpDefault,
63 IntPtr lpReturnedString,
64 uint nSize,
65 string lpFileName);
66
67 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
68 public static extern int GetPrivateProfileInt(string lpAppName,
69 string lpKeyName,
70 int lpDefault,
71 string lpFileName);
72
73 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
74 public static extern int GetPrivateProfileSection(string lpAppName,
75 IntPtr lpReturnedString,
76 uint nSize,
77 string lpFileName);
78
79 //We explicitly enable the SetLastError attribute here because
80 // WritePrivateProfileString returns errors via SetLastError.
81 // Failure to set this can result in errors being lost during
82 // the marshal back to managed code.
83 [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
84 public static extern bool WritePrivateProfileString(string lpAppName,
85 string lpKeyName,
86 string lpString,
87 string lpFileName);
88
89
90 }
91 #endregion
92
93 /// <summary>
94 /// Initializes a new instance of the <see cref="IniFileHelp"/> class.
95 /// </summary>
96 /// <param name="path">The ini file to read and write from.</param>
97 public IniFileHelp(string path)
98 {
99 //Convert to the full path. Because of backward compatibility,
100 // the win32 functions tend to assume the path should be the
101 // root Windows directory if it is not specified. By calling
102 // GetFullPath, we make sure we are always passing the full path
103 // the win32 functions.
104 m_path = System.IO.Path.GetFullPath(path);
105 }
106
107 /// <summary>
108 /// Gets the full path of ini file this object instance is operating on.
109 /// </summary>
110 /// <value>A file path.</value>
111 public string Path
112 {
113 get
114 {
115 return m_path;
116 }
117 }
118
119 #region Get Value Methods
120
121 /// <summary>
122 /// Gets the value of a setting in an ini file as a <see cref="T:System.String"/>.
123 /// </summary>
124 /// <param name="sectionName">The name of the section to read from.</param>
125 /// <param name="keyName">The name of the key in section to read.</param>
126 /// <param name="defaultValue">The default value to return if the key
127 /// cannot be found.</param>
128 /// <returns>The value of the key, if found. Otherwise, returns
129 /// <paramref name="defaultValue"/></returns>
130 /// <remarks>
131 /// The retreived value must be less than 32KB in length.
132 /// </remarks>
133 /// <exception cref="ArgumentNullException">
134 /// <paramref name="sectionName"/> or <paramref name="keyName"/> are
135 /// a null reference (Nothing in VB)
136 /// </exception>
137 public string GetString(string sectionName,
138 string keyName,
139 string defaultValue)
140 {
141 if (sectionName == null)
142 throw new ArgumentNullException("sectionName");
143
144 if (keyName == null)
145 throw new ArgumentNullException("keyName");
146
147 StringBuilder retval = new StringBuilder(IniFileHelp.MaxSectionSize);
148
149 NativeMethods.GetPrivateProfileString(sectionName,
150 keyName,
151 defaultValue,
152 retval,
153 IniFileHelp.MaxSectionSize,
154 m_path);
155
156 return retval.ToString();
157 }
158
159 /// <summary>
160 /// Gets the value of a setting in an ini file as a <see cref="T:System.Int16"/>.
161 /// </summary>
162 /// <param name="sectionName">The name of the section to read from.</param>
163 /// <param name="keyName">The name of the key in section to read.</param>
164 /// <param name="defaultValue">The default value to return if the key
165 /// cannot be found.</param>
166 /// <returns>The value of the key, if found. Otherwise, returns
167 /// <paramref name="defaultValue"/>.</returns>
168 /// <exception cref="ArgumentNullException">
169 /// <paramref name="sectionName"/> or <paramref name="keyName"/> are
170 /// a null reference (Nothing in VB)
171 /// </exception>
172 public int GetInt16(string sectionName,
173 string keyName,
174 short defaultValue)
175 {
176 int retval = GetInt32(sectionName, keyName, defaultValue);
177
178 return Convert.ToInt16(retval);
179 }
180
181 /// <summary>
182 /// Gets the value of a setting in an ini file as a <see cref="T:System.Int32"/>.
183 /// </summary>
184 /// <param name="sectionName">The name of the section to read from.</param>
185 /// <param name="keyName">The name of the key in section to read.</param>
186 /// <param name="defaultValue">The default value to return if the key
187 /// cannot be found.</param>
188 /// <returns>The value of the key, if found. Otherwise, returns
189 /// <paramref name="defaultValue"/></returns>
190 /// <exception cref="ArgumentNullException">
191 /// <paramref name="sectionName"/> or <paramref name="keyName"/> are
192 /// a null reference (Nothing in VB)
193 /// </exception>
194 public int GetInt32(string sectionName,
195 string keyName,
196 int defaultValue)
197 {
198 if (sectionName == null)
199 throw new ArgumentNullException("sectionName");
200
201 if (keyName == null)
202 throw new ArgumentNullException("keyName");
203
204
205 return NativeMethods.GetPrivateProfileInt(sectionName, keyName, defaultValue, m_path);
206 }
207
208 /// <summary>
209 /// Gets the value of a setting in an ini file as a <see cref="T:System.Double"/>.
210 /// </summary>
211 /// <param name="sectionName">The name of the section to read from.</param>
212 /// <param name="keyName">The name of the key in section to read.</param>
213 /// <param name="defaultValue">The default value to return if the key
214 /// cannot be found.</param>
215 /// <returns>The value of the key, if found. Otherwise, returns
216 /// <paramref name="defaultValue"/></returns>
217 /// <exception cref="ArgumentNullException">
218 /// <paramref name="sectionName"/> or <paramref name="keyName"/> are
219 /// a null reference (Nothing in VB)
220 /// </exception>
221 public double GetDouble(string sectionName,
222 string keyName,
223 double defaultValue)
224 {
225 string retval = GetString(sectionName, keyName, "");
226
227 if (retval == null || retval.Length == 0)
228 {
229 return defaultValue;
230 }
231
232 return Convert.ToDouble(retval, CultureInfo.InvariantCulture);
233 }
234
235 #endregion
236
237 #region GetSectionValues Methods
238
239 /// <summary>
240 /// Gets all of the values in a section as a list.
241 /// </summary>
242 /// <param name="sectionName">
243 /// Name of the section to retrieve values from.
244 /// </param>
245 /// <returns>
246 /// A <see cref="List{T}"/> containing <see cref="KeyValuePair{T1, T2}"/> objects
247 /// that describe this section. Use this verison if a section may contain
248 /// multiple items with the same key value. If you know that a section
249 /// cannot contain multiple values with the same key name or you don't
250 /// care about the duplicates, use the more convenient
251 /// <see cref="GetSectionValues"/> function.
252 /// </returns>
253 /// <exception cref="ArgumentNullException">
254 /// <paramref name="sectionName"/> is a null reference (Nothing in VB)
255 /// </exception>
256 public List<KeyValuePair<string, string>> GetSectionValuesAsList(string sectionName)
257 {
258 List<KeyValuePair<string, string>> retval;
259 string[] keyValuePairs;
260 string key, value;
261 int equalSignPos;
262
263 if (sectionName == null)
264 throw new ArgumentNullException("sectionName");
265
266 //Allocate a buffer for the returned section names.
267 IntPtr ptr = Marshal.AllocCoTaskMem(IniFileHelp.MaxSectionSize);
268
269 try
270 {
271 //Get the section key/value pairs into the buffer.
272 int len = NativeMethods.GetPrivateProfileSection(sectionName,
273 ptr,
274 IniFileHelp.MaxSectionSize,
275 m_path);
276
277 keyValuePairs = ConvertNullSeperatedStringToStringArray(ptr, len);
278 }
279 finally
280 {
281 //Free the buffer
282 Marshal.FreeCoTaskMem(ptr);
283 }
284
285 //Parse keyValue pairs and add them to the list.
286 retval = new List<KeyValuePair<string, string>>(keyValuePairs.Length);
287
288 for (int i = 0; i < keyValuePairs.Length; ++i)
289 {
290 //Parse the "key=value" string into its constituent parts
291 //Cancel a string start with '#'
292 var item = keyValuePairs[i].Trim();
293 if (item.Length > 0 && !item.StartsWith("#"))
294 {
295 equalSignPos = keyValuePairs[i].IndexOf('=');
296 key = keyValuePairs[i].Substring(0, equalSignPos);
297
298 value = keyValuePairs[i].Substring(equalSignPos + 1,
299 keyValuePairs[i].Length - equalSignPos - 1);
300
301 retval.Add(new KeyValuePair<string, string>(key, value));
302 }
303 }
304
305 return retval;
306 }
307
308 /// <summary>
309 /// Gets all of the values in a section as a dictionary.
310 /// </summary>
311 /// <param name="sectionName">
312 /// Name of the section to retrieve values from.
313 /// </param>
314 /// <returns>
315 /// A <see cref="Dictionary{T, T}"/> containing the key/value
316 /// pairs found in this section.
317 /// </returns>
318 /// <remarks>
319 /// If a section contains more than one key with the same name,
320 /// this function only returns the first instance. If you need to
321 /// get all key/value pairs within a section even when keys have the
322 /// same name, use <see cref="GetSectionValuesAsList"/>.
323 /// </remarks>
324 /// <exception cref="ArgumentNullException">
325 /// <paramref name="sectionName"/> is a null reference (Nothing in VB)
326 /// </exception>
327 public Dictionary<string, string> GetSectionValues(string sectionName)
328 {
329 List<KeyValuePair<string, string>> keyValuePairs;
330 Dictionary<string, string> retval;
331
332 keyValuePairs = GetSectionValuesAsList(sectionName);
333
334 //Convert list into a dictionary.
335 retval = new Dictionary<string, string>(keyValuePairs.Count);
336
337 foreach (KeyValuePair<string, string> keyValuePair in keyValuePairs)
338 {
339 //Skip any key we have already seen.
340 if (!retval.ContainsKey(keyValuePair.Key))
341 {
342 retval.Add(keyValuePair.Key, keyValuePair.Value);
343 }
344 }
345
346 return retval;
347 }
348
349 #endregion
350
351 #region Get Key/Section Names
352
353 /// <summary>
354 /// Gets the names of all keys under a specific section in the ini file.
355 /// </summary>
356 /// <param name="sectionName">
357 /// The name of the section to read key names from.
358 /// </param>
359 /// <returns>An array of key names.</returns>
360 /// <remarks>
361 /// The total length of all key names in the section must be
362 /// less than 32KB in length.
363 /// </remarks>
364 /// <exception cref="ArgumentNullException">
365 /// <paramref name="sectionName"/> is a null reference (Nothing in VB)
366 /// </exception>
367 public string[] GetKeyNames(string sectionName)
368 {
369 int len;
370 string[] retval;
371
372 if (sectionName == null)
373 throw new ArgumentNullException("sectionName");
374
375 //Allocate a buffer for the returned section names.
376 IntPtr ptr = Marshal.AllocCoTaskMem(IniFileHelp.MaxSectionSize);
377
378 try
379 {
380 //Get the section names into the buffer.
381 len = NativeMethods.GetPrivateProfileString(sectionName,
382 null,
383 null,
384 ptr,
385 IniFileHelp.MaxSectionSize,
386 m_path);
387
388 retval = ConvertNullSeperatedStringToStringArray(ptr, len);
389 }
390 finally
391 {
392 //Free the buffer
393 Marshal.FreeCoTaskMem(ptr);
394 }
395
396 return retval;
397 }
398
399 /// <summary>
400 /// Gets the names of all sections in the ini file.
401 /// </summary>
402 /// <returns>An array of section names.</returns>
403 /// <remarks>
404 /// The total length of all section names in the section must be
405 /// less than 32KB in length.
406 /// </remarks>
407 public string[] GetSectionNames()
408 {
409 string[] retval;
410 int len;
411
412 //Allocate a buffer for the returned section names.
413 IntPtr ptr = Marshal.AllocCoTaskMem(IniFileHelp.MaxSectionSize);
414
415 try
416 {
417 //Get the section names into the buffer.
418 len = NativeMethods.GetPrivateProfileSectionNames(ptr,
419 IniFileHelp.MaxSectionSize, m_path);
420
421 retval = ConvertNullSeperatedStringToStringArray(ptr, len);
422 }
423 finally
424 {
425 //Free the buffer
426 Marshal.FreeCoTaskMem(ptr);
427 }
428
429 return retval;
430 }
431
432 /// <summary>
433 /// Converts the null seperated pointer to a string into a string array.
434 /// </summary>
435 /// <param name="ptr">A pointer to string data.</param>
436 /// <param name="valLength">
437 /// Length of the data pointed to by <paramref name="ptr"/>.
438 /// </param>
439 /// <returns>
440 /// An array of strings; one for each null found in the array of characters pointed
441 /// at by <paramref name="ptr"/>.
442 /// </returns>
443 private static string[] ConvertNullSeperatedStringToStringArray(IntPtr ptr, int valLength)
444 {
445 string[] retval;
446
447 if (valLength == 0)
448 {
449 //Return an empty array.
450 retval = new string[0];
451 }
452 else
453 {
454 //Convert the buffer into a string. Decrease the length
455 //by 1 so that we remove the second null off the end.
456 string buff = Marshal.PtrToStringAuto(ptr, valLength - 1);
457
458 //Parse the buffer into an array of strings by searching for nulls.
459 retval = buff.Split('\0');
460 }
461
462 return retval;
463 }
464
465 #endregion
466
467 #region Write Methods
468
469 /// <summary>
470 /// Writes a <see cref="T:System.String"/> value to the ini file.
471 /// </summary>
472 /// <param name="sectionName">The name of the section to write to .</param>
473 /// <param name="keyName">The name of the key to write to.</param>
474 /// <param name="value">The string value to write</param>
475 /// <exception cref="T:System.ComponentModel.Win32Exception">
476 /// The write failed.
477 /// </exception>
478 private void WriteValueInternal(string sectionName, string keyName, string value)
479 {
480 if (!NativeMethods.WritePrivateProfileString(sectionName, keyName, value, m_path))
481 {
482 throw new System.ComponentModel.Win32Exception();
483 }
484 }
485
486 /// <summary>
487 /// Writes a <see cref="T:System.String"/> value to the ini file.
488 /// </summary>
489 /// <param name="sectionName">The name of the section to write to .</param>
490 /// <param name="keyName">The name of the key to write to.</param>
491 /// <param name="value">The string value to write</param>
492 /// <exception cref="T:System.ComponentModel.Win32Exception">
493 /// The write failed.
494 /// </exception>
495 /// <exception cref="ArgumentNullException">
496 /// <paramref name="sectionName"/> or <paramref name="keyName"/> or
497 /// <paramref name="value"/> are a null reference (Nothing in VB)
498 /// </exception>
499 public void WriteValue(string sectionName, string keyName, string value)
500 {
501 if (sectionName == null)
502 throw new ArgumentNullException("sectionName");
503
504 if (keyName == null)
505 throw new ArgumentNullException("keyName");
506
507 if (value == null)
508 throw new ArgumentNullException("value");
509
510 WriteValueInternal(sectionName, keyName, value);
511 }
512
513 /// <summary>
514 /// Writes an <see cref="T:System.Int16"/> value to the ini file.
515 /// </summary>
516 /// <param name="sectionName">The name of the section to write to .</param>
517 /// <param name="keyName">The name of the key to write to.</param>
518 /// <param name="value">The value to write</param>
519 /// <exception cref="T:System.ComponentModel.Win32Exception">
520 /// The write failed.
521 /// </exception>
522 public void WriteValue(string sectionName, string keyName, short value)
523 {
524 WriteValue(sectionName, keyName, (int)value);
525 }
526
527 /// <summary>
528 /// Writes an <see cref="T:System.Int32"/> value to the ini file.
529 /// </summary>
530 /// <param name="sectionName">The name of the section to write to .</param>
531 /// <param name="keyName">The name of the key to write to.</param>
532 /// <param name="value">The value to write</param>
533 /// <exception cref="T:System.ComponentModel.Win32Exception">
534 /// The write failed.
535 /// </exception>
536 /// <exception cref="ArgumentNullException">
537 /// <paramref name="sectionName"/> or <paramref name="keyName"/> are
538 /// a null reference (Nothing in VB)
539 /// </exception>
540 public void WriteValue(string sectionName, string keyName, int value)
541 {
542 WriteValue(sectionName, keyName, value.ToString(CultureInfo.InvariantCulture));
543 }
544
545 /// <summary>
546 /// Writes an <see cref="T:System.Single"/> value to the ini file.
547 /// </summary>
548 /// <param name="sectionName">The name of the section to write to .</param>
549 /// <param name="keyName">The name of the key to write to.</param>
550 /// <param name="value">The value to write</param>
551 /// <exception cref="T:System.ComponentModel.Win32Exception">
552 /// The write failed.
553 /// </exception>
554 /// <exception cref="ArgumentNullException">
555 /// <paramref name="sectionName"/> or <paramref name="keyName"/> are
556 /// a null reference (Nothing in VB)
557 /// </exception>
558 public void WriteValue(string sectionName, string keyName, float value)
559 {
560 WriteValue(sectionName, keyName, value.ToString(CultureInfo.InvariantCulture));
561 }
562
563 /// <summary>
564 /// Writes an <see cref="T:System.Double"/> value to the ini file.
565 /// </summary>
566 /// <param name="sectionName">The name of the section to write to .</param>
567 /// <param name="keyName">The name of the key to write to.</param>
568 /// <param name="value">The value to write</param>
569 /// <exception cref="T:System.ComponentModel.Win32Exception">
570 /// The write failed.
571 /// </exception>
572 /// <exception cref="ArgumentNullException">
573 /// <paramref name="sectionName"/> or <paramref name="keyName"/> are
574 /// a null reference (Nothing in VB)
575 /// </exception>
576 public void WriteValue(string sectionName, string keyName, double value)
577 {
578 WriteValue(sectionName, keyName, value.ToString(CultureInfo.InvariantCulture));
579 }
580
581 #endregion
582
583 #region Delete Methods
584
585 /// <summary>
586 /// Deletes the specified key from the specified section.
587 /// </summary>
588 /// <param name="sectionName">
589 /// Name of the section to remove the key from.
590 /// </param>
591 /// <param name="keyName">
592 /// Name of the key to remove.
593 /// </param>
594 /// <exception cref="ArgumentNullException">
595 /// <paramref name="sectionName"/> or <paramref name="keyName"/> are
596 /// a null reference (Nothing in VB)
597 /// </exception>
598 public void DeleteKey(string sectionName, string keyName)
599 {
600 if (sectionName == null)
601 throw new ArgumentNullException("sectionName");
602
603 if (keyName == null)
604 throw new ArgumentNullException("keyName");
605
606 WriteValueInternal(sectionName, keyName, null);
607 }
608
609 /// <summary>
610 /// Deletes a section from the ini file.
611 /// </summary>
612 /// <param name="sectionName">
613 /// Name of the section to delete.
614 /// </param>
615 /// <exception cref="ArgumentNullException">
616 /// <paramref name="sectionName"/> is a null reference (Nothing in VB)
617 /// </exception>
618 public void DeleteSection(string sectionName)
619 {
620 if (sectionName == null)
621 throw new ArgumentNullException("sectionName");
622
623 WriteValueInternal(sectionName, null, null);
624 }
625
626 #endregion
627 }
来源:https://www.cnblogs.com/codealone/p/3371057.html
