C# 使用文件流来读写ini文件
2013-10-15 21:37
671 查看
背景
之前采用ini文件作为程序的配置文件,觉得这种结构简单明了,配置起来也挺方便。然后操作方式是通过WindowsAPI,然后再网上找到一个基于WindowsAPI封装的help类,用起来倒也顺手。用的多了,觉得还可以使用文件流来操作,后来就发现了EasyConfig。EasyConfig是一个纯C#的开源ini文件操作库,但是在使用上有诸多不便,只是个人感觉,于是个人将其改造了一下,是自己喜欢用的风格。
资源下载
如果不清楚ini文件结构,请百度一下,这里贴一个示例文件。/// <summary> /// Provides methods for reading and writing to an INI file. /// </summary> public class IniFileHelp { /// <summary> /// The maximum size of a section in an ini file. /// </summary> /// <remarks> /// This property defines the maximum size of the buffers /// used to retreive data from an ini file. This value is /// the maximum allowed by the win32 functions /// GetPrivateProfileSectionNames() or /// GetPrivateProfileString(). /// </remarks> public const int MaxSectionSize = 32767; // 32 KB //The path of the file we are operating on. private string m_path; #region P/Invoke declares /// <summary> /// A static class that provides the win32 P/Invoke signatures /// used by this class. /// </summary> /// <remarks> /// Note: In each of the declarations below, we explicitly set CharSet to /// Auto. By default in C#, CharSet is set to Ansi, which reduces /// performance on windows 2000 and above due to needing to convert strings /// from Unicode (the native format for all .Net strings) to Ansi before /// marshalling. Using Auto lets the marshaller select the Unicode version of /// these functions when available. /// </remarks> [System.Security.SuppressUnmanagedCodeSecurity] private static class NativeMethods { [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern int GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer, uint nSize, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, int nSize, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, [In, Out] char[] lpReturnedString, int nSize, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern int GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, IntPtr lpReturnedString, uint nSize, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern int GetPrivateProfileInt(string lpAppName, string lpKeyName, int lpDefault, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern int GetPrivateProfileSection(string lpAppName, IntPtr lpReturnedString, uint nSize, string lpFileName); //We explicitly enable the SetLastError attribute here because // WritePrivateProfileString returns errors via SetLastError. // Failure to set this can result in errors being lost during // the marshal back to managed code. [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName); } #endregion /// <summary> /// Initializes a new instance of the <see cref="IniFileHelp"/> class. /// </summary> /// <param name="path">The ini file to read and write from.</param> public IniFileHelp(string path) { //Convert to the full path. Because of backward compatibility, // the win32 functions tend to assume the path should be the // root Windows directory if it is not specified. By calling // GetFullPath, we make sure we are always passing the full path // the win32 functions. m_path = System.IO.Path.GetFullPath(path); } /// <summary> /// Gets the full path of ini file this object instance is operating on. /// </summary> /// <value>A file path.</value> public string Path { get { return m_path; } } #region Get Value Methods /// <summary> /// Gets the value of a setting in an ini file as a <see cref="T:System.String"/>. /// </summary> /// <param name="sectionName">The name of the section to read from.</param> /// <param name="keyName">The name of the key in section to read.</param> /// <param name="defaultValue">The default value to return if the key /// cannot be found.</param> /// <returns>The value of the key, if found. Otherwise, returns /// <paramref name="defaultValue"/></returns> /// <remarks> /// The retreived value must be less than 32KB in length. /// </remarks> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> or <paramref name="keyName"/> are /// a null reference (Nothing in VB) /// </exception> public string GetString(string sectionName, string keyName, string defaultValue) { if (sectionName == null) throw new ArgumentNullException("sectionName"); if (keyName == null) throw new ArgumentNullException("keyName"); StringBuilder retval = new StringBuilder(IniFileHelp.MaxSectionSize); NativeMethods.GetPrivateProfileString(sectionName, keyName, defaultValue, retval, IniFileHelp.MaxSectionSize, m_path); return retval.ToString(); } /// <summary> /// Gets the value of a setting in an ini file as a <see cref="T:System.Int16"/>. /// </summary> /// <param name="sectionName">The name of the section to read from.</param> /// <param name="keyName">The name of the key in section to read.</param> /// <param name="defaultValue">The default value to return if the key /// cannot be found.</param> /// <returns>The value of the key, if found. Otherwise, returns /// <paramref name="defaultValue"/>.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> or <paramref name="keyName"/> are /// a null reference (Nothing in VB) /// </exception> public int GetInt16(string sectionName, string keyName, short defaultValue) { int retval = GetInt32(sectionName, keyName, defaultValue); return Convert.ToInt16(retval); } /// <summary> /// Gets the value of a setting in an ini file as a <see cref="T:System.Int32"/>. /// </summary> /// <param name="sectionName">The name of the section to read from.</param> /// <param name="keyName">The name of the key in section to read.</param> /// <param name="defaultValue">The default value to return if the key /// cannot be found.</param> /// <returns>The value of the key, if found. Otherwise, returns /// <paramref name="defaultValue"/></returns> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> or <paramref name="keyName"/> are /// a null reference (Nothing in VB) /// </exception> public int GetInt32(string sectionName, string keyName, int defaultValue) { if (sectionName == null) throw new ArgumentNullException("sectionName"); if (keyName == null) throw new ArgumentNullException("keyName"); return NativeMethods.GetPrivateProfileInt(sectionName, keyName, defaultValue, m_path); } /// <summary> /// Gets the value of a setting in an ini file as a <see cref="T:System.Double"/>. /// </summary> /// <param name="sectionName">The name of the section to read from.</param> /// <param name="keyName">The name of the key in section to read.</param> /// <param name="defaultValue">The default value to return if the key /// cannot be found.</param> /// <returns>The value of the key, if found. Otherwise, returns /// <paramref name="defaultValue"/></returns> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> or <paramref name="keyName"/> are /// a null reference (Nothing in VB) /// </exception> public double GetDouble(string sectionName, string keyName, double defaultValue) { string retval = GetString(sectionName, keyName, ""); if (retval == null || retval.Length == 0) { return defaultValue; } return Convert.ToDouble(retval, CultureInfo.InvariantCulture); } #endregion #region GetSectionValues Methods /// <summary> /// Gets all of the values in a section as a list. /// </summary> /// <param name="sectionName"> /// Name of the section to retrieve values from. /// </param> /// <returns> /// A <see cref="List{T}"/> containing <see cref="KeyValuePair{T1, T2}"/> objects /// that describe this section. Use this verison if a section may contain /// multiple items with the same key value. If you know that a section /// cannot contain multiple values with the same key name or you don't /// care about the duplicates, use the more convenient /// <see cref="GetSectionValues"/> function. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> is a null reference (Nothing in VB) /// </exception> public List<KeyValuePair<string, string>> GetSectionValuesAsList(string sectionName) { List<KeyValuePair<string, string>> retval; string[] keyValuePairs; string key, value; int equalSignPos; if (sectionName == null) throw new ArgumentNullException("sectionName"); //Allocate a buffer for the returned section names. IntPtr ptr = Marshal.AllocCoTaskMem(IniFileHelp.MaxSectionSize); try { //Get the section key/value pairs into the buffer. int len = NativeMethods.GetPrivateProfileSection(sectionName, ptr, IniFileHelp.MaxSectionSize, m_path); keyValuePairs = ConvertNullSeperatedStringToStringArray(ptr, len); } finally { //Free the buffer Marshal.FreeCoTaskMem(ptr); } //Parse keyValue pairs and add them to the list. retval = new List<KeyValuePair<string, string>>(keyValuePairs.Length); for (int i = 0; i < keyValuePairs.Length; ++i) { //Parse the "key=value" string into its constituent parts //Cancel a string start with '#' var item = keyValuePairs[i].Trim(); if (item.Length > 0 && !item.StartsWith("#")) { equalSignPos = keyValuePairs[i].IndexOf('='); key = keyValuePairs[i].Substring(0, equalSignPos); value = keyValuePairs[i].Substring(equalSignPos + 1, keyValuePairs[i].Length - equalSignPos - 1); retval.Add(new KeyValuePair<string, string>(key, value)); } } return retval; } /// <summary> /// Gets all of the values in a section as a dictionary. /// </summary> /// <param name="sectionName"> /// Name of the section to retrieve values from. /// </param> /// <returns> /// A <see cref="Dictionary{T, T}"/> containing the key/value /// pairs found in this section. /// </returns> /// <remarks> /// If a section contains more than one key with the same name, /// this function only returns the first instance. If you need to /// get all key/value pairs within a section even when keys have the /// same name, use <see cref="GetSectionValuesAsList"/>. /// </remarks> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> is a null reference (Nothing in VB) /// </exception> public Dictionary<string, string> GetSectionValues(string sectionName) { List<KeyValuePair<string, string>> keyValuePairs; Dictionary<string, string> retval; keyValuePairs = GetSectionValuesAsList(sectionName); //Convert list into a dictionary. retval = new Dictionary<string, string>(keyValuePairs.Count); foreach (KeyValuePair<string, string> keyValuePair in keyValuePairs) { //Skip any key we have already seen. if (!retval.ContainsKey(keyValuePair.Key)) { retval.Add(keyValuePair.Key, keyValuePair.Value); } } return retval; } #endregion #region Get Key/Section Names /// <summary> /// Gets the names of all keys under a specific section in the ini file. /// </summary> /// <param name="sectionName"> /// The name of the section to read key names from. /// </param> /// <returns>An array of key names.</returns> /// <remarks> /// The total length of all key names in the section must be /// less than 32KB in length. /// </remarks> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> is a null reference (Nothing in VB) /// </exception> public string[] GetKeyNames(string sectionName) { int len; string[] retval; if (sectionName == null) throw new ArgumentNullException("sectionName"); //Allocate a buffer for the returned section names. IntPtr ptr = Marshal.AllocCoTaskMem(IniFileHelp.MaxSectionSize); try { //Get the section names into the buffer. len = NativeMethods.GetPrivateProfileString(sectionName, null, null, ptr, IniFileHelp.MaxSectionSize, m_path); retval = ConvertNullSeperatedStringToStringArray(ptr, len); } finally { //Free the buffer Marshal.FreeCoTaskMem(ptr); } return retval; } /// <summary> /// Gets the names of all sections in the ini file. /// </summary> /// <returns>An array of section names.</returns> /// <remarks> /// The total length of all section names in the section must be /// less than 32KB in length. /// </remarks> public string[] GetSectionNames() { string[] retval; int len; //Allocate a buffer for the returned section names. IntPtr ptr = Marshal.AllocCoTaskMem(IniFileHelp.MaxSectionSize); try { //Get the section names into the buffer. len = NativeMethods.GetPrivateProfileSectionNames(ptr, IniFileHelp.MaxSectionSize, m_path); retval = ConvertNullSeperatedStringToStringArray(ptr, len); } finally { //Free the buffer Marshal.FreeCoTaskMem(ptr); } return retval; } /// <summary> /// Converts the null seperated pointer to a string into a string array. /// </summary> /// <param name="ptr">A pointer to string data.</param> /// <param name="valLength"> /// Length of the data pointed to by <paramref name="ptr"/>. /// </param> /// <returns> /// An array of strings; one for each null found in the array of characters pointed /// at by <paramref name="ptr"/>. /// </returns> private static string[] ConvertNullSeperatedStringToStringArray(IntPtr ptr, int valLength) { string[] retval; if (valLength == 0) { //Return an empty array. retval = new string[0]; } else { //Convert the buffer into a string. Decrease the length //by 1 so that we remove the second null off the end. string buff = Marshal.PtrToStringAuto(ptr, valLength - 1); //Parse the buffer into an array of strings by searching for nulls. retval = buff.Split('\0'); } return retval; } #endregion #region Write Methods /// <summary> /// Writes a <see cref="T:System.String"/> value to the ini file. /// </summary> /// <param name="sectionName">The name of the section to write to .</param> /// <param name="keyName">The name of the key to write to.</param> /// <param name="value">The string value to write</param> /// <exception cref="T:System.ComponentModel.Win32Exception"> /// The write failed. /// </exception> private void WriteValueInternal(string sectionName, string keyName, string value) { if (!NativeMethods.WritePrivateProfileString(sectionName, keyName, value, m_path)) { throw new System.ComponentModel.Win32Exception(); } } /// <summary> /// Writes a <see cref="T:System.String"/> value to the ini file. /// </summary> /// <param name="sectionName">The name of the section to write to .</param> /// <param name="keyName">The name of the key to write to.</param> /// <param name="value">The string value to write</param> /// <exception cref="T:System.ComponentModel.Win32Exception"> /// The write failed. /// </exception> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> or <paramref name="keyName"/> or /// <paramref name="value"/> are a null reference (Nothing in VB) /// </exception> public void WriteValue(string sectionName, string keyName, string value) { if (sectionName == null) throw new ArgumentNullException("sectionName"); if (keyName == null) throw new ArgumentNullException("keyName"); if (value == null) throw new ArgumentNullException("value"); WriteValueInternal(sectionName, keyName, value); } /// <summary> /// Writes an <see cref="T:System.Int16"/> value to the ini file. /// </summary> /// <param name="sectionName">The name of the section to write to .</param> /// <param name="keyName">The name of the key to write to.</param> /// <param name="value">The value to write</param> /// <exception cref="T:System.ComponentModel.Win32Exception"> /// The write failed. /// </exception> public void WriteValue(string sectionName, string keyName, short value) { WriteValue(sectionName, keyName, (int)value); } /// <summary> /// Writes an <see cref="T:System.Int32"/> value to the ini file. /// </summary> /// <param name="sectionName">The name of the section to write to .</param> /// <param name="keyName">The name of the key to write to.</param> /// <param name="value">The value to write</param> /// <exception cref="T:System.ComponentModel.Win32Exception"> /// The write failed. /// </exception> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> or <paramref name="keyName"/> are /// a null reference (Nothing in VB) /// </exception> public void WriteValue(string sectionName, string keyName, int value) { WriteValue(sectionName, keyName, value.ToString(CultureInfo.InvariantCulture)); } /// <summary> /// Writes an <see cref="T:System.Single"/> value to the ini file. /// </summary> /// <param name="sectionName">The name of the section to write to .</param> /// <param name="keyName">The name of the key to write to.</param> /// <param name="value">The value to write</param> /// <exception cref="T:System.ComponentModel.Win32Exception"> /// The write failed. /// </exception> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> or <paramref name="keyName"/> are /// a null reference (Nothing in VB) /// </exception> public void WriteValue(string sectionName, string keyName, float value) { WriteValue(sectionName, keyName, value.ToString(CultureInfo.InvariantCulture)); } /// <summary> /// Writes an <see cref="T:System.Double"/> value to the ini file. /// </summary> /// <param name="sectionName">The name of the section to write to .</param> /// <param name="keyName">The name of the key to write to.</param> /// <param name="value">The value to write</param> /// <exception cref="T:System.ComponentModel.Win32Exception"> /// The write failed. /// </exception> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> or <paramref name="keyName"/> are /// a null reference (Nothing in VB) /// </exception> public void WriteValue(string sectionName, string keyName, double value) { WriteValue(sectionName, keyName, value.ToString(CultureInfo.InvariantCulture)); } #endregion #region Delete Methods /// <summary> /// Deletes the specified key from the specified section. /// </summary> /// <param name="sectionName"> /// Name of the section to remove the key from. /// </param> /// <param name="keyName"> /// Name of the key to remove. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> or <paramref name="keyName"/> are /// a null reference (Nothing in VB) /// </exception> public void DeleteKey(string sectionName, string keyName) { if (sectionName == null) throw new ArgumentNullException("sectionName"); if (keyName == null) throw new ArgumentNullException("keyName"); WriteValueInternal(sectionName, keyName, null); } /// <summary> /// Deletes a section from the ini file. /// </summary> /// <param name="sectionName"> /// Name of the section to delete. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="sectionName"/> is a null reference (Nothing in VB) /// </exception> public void DeleteSection(string sectionName) { if (sectionName == null) throw new ArgumentNullException("sectionName"); WriteValueInternal(sectionName, null, null); } #endregion }
IniFileHelp
相关文章推荐
- 使用nini开源类库实现c#对ini文件的读写
- C# 使用API读写Ini文件的类
- C#使用Linq读写ini文件
- inieditor基于注解的扩展使用(java读写.ini文件)
- [c#]:如何在C#中读写INI文件(五)
- C#中如何读写INI文件
- c#读写excel文件使用示例
- [c#]读写ini文件
- C#读取ini文件方法,实质是使用C++的库
- C#使用MemoryStream类读写内存
- C#读写INI文件的方法
- C# 读写ini文件
- C#读写INI文件
- C#如何读写和创建INI文件
- C# 使用SQLite数据库 之 读写数据库
- C#不使用DataSet操作XML,XmlDocument读写xml所有节点及读取xml节点的数据总结
- C# 读写ini文件
- C#读写ini文件详解
- C#读写INI文件
- C#读写和创建INI文件