C++针对ini配置文件读写大全

ini文件(Initialization file),这种类型的文件中通常存放的是一个程序的初始化信息。ini文件由若干个节(Section)组成,每个Section由若干键(Key)组成,每个Key可以赋相应的值。读写ini文件实际上就是读写某个的Section中相应的Key的值,而这只要借助几个函数即可完成。

1. 把信息写入系统的win.ini文件

  1. BOOL WriteProfileString(
  2. LPCTSTR lpAppName, // 节的名字,是一个以0结束的字符串
  3. LPCTSTR lpKeyName, // 键的名字,是一个以0结束的字符串。若为NULL,则删除整个节
  4. LPCTSTR lpString // 键的值,是一个以0结束的字符串。若为NULL,则删除对应的键
  5. )
BOOL WriteProfileString(
LPCTSTR lpAppName,   // 节的名字,是一个以0结束的字符串
LPCTSTR lpKeyName,   // 键的名字,是一个以0结束的字符串。若为NULL,则删除整个节
LPCTSTR lpString       // 键的值,是一个以0结束的字符串。若为NULL,则删除对应的键
)

2、从系统的win.ini文件中读取信息

  1. DWORD GetProfileString(
  2. LPCTSTR lpAppName, // 节名
  3. LPCTSTR lpKeyName, // 键名,读取该键的值
  4. LPCTSTR lpDefault, // 若指定的键不存在,该值作为读取的默认值
  5. LPTSTR lpReturnedString, // 一个指向缓冲区的指针,接收读取的字符串
  6. DWORD nSize // 指定lpReturnedString指向的缓冲区的大小
  7. )
DWORD GetProfileString(
LPCTSTR lpAppName,      // 节名
LPCTSTR lpKeyName,       // 键名,读取该键的值
LPCTSTR lpDefault,        // 若指定的键不存在,该值作为读取的默认值
LPTSTR lpReturnedString,   // 一个指向缓冲区的指针,接收读取的字符串
DWORD nSize             // 指定lpReturnedString指向的缓冲区的大小
)
  1. UINT GetProfileInt(
  2. LPCTSTR lpAppName, // 同上
  3. LPCTSTR lpKeyName, // 同上
  4. INT nDefault // 若指定的键名不存在,该值作为读取的默认值
  5. )
UINT GetProfileInt(
LPCTSTR lpAppName,      // 同上
LPCTSTR lpKeyName,       // 同上
INT nDefault               // 若指定的键名不存在,该值作为读取的默认值
)

3.写入读取自己的ini

简单的INI例子:

  1. [Service]
  2. Name=AutoRun Helper
  3. Description=200
  4. ApplicationRootKey64=Software\Wow6432Node\Sepang\AutoRun Modem
  5. [Registry]
  6. ServiceRootKey=Software\AutoRun Modem Service
  7. ApplicationRootKey=Software\Sepang\AutoRun Modem
  8. ApplicationRootKey64=Software\Wow6432Node\Sepang\AutoRun Modem
[Service]
Name=AutoRun Helper
Description=200
ApplicationRootKey64=Software\Wow6432Node\Sepang\AutoRun Modem
[Registry]
ServiceRootKey=Software\AutoRun Modem Service
ApplicationRootKey=Software\Sepang\AutoRun Modem
ApplicationRootKey64=Software\Wow6432Node\Sepang\AutoRun Modem


下面示例显示它是如何生成的:

  1. void XXXXX::OnBnClickedWriteIniBtn()
  2. {
  3. // ----------------------------------------
  4. // 模拟写入一个config.ini
  5. // ----------------------------------------
  6.  
  7. // 得到exe执行路径.
  8. TCHAR tcExePath[MAX_PATH] = {0};
  9. ::GetModuleFileName(NULL, tcExePath, MAX_PATH);
  10. // 设置ini路径到exe同一目录下
  11. #ifndef CONFIG_FILE
  12. #define CONFIG_FILE (TEXT("Config1.ini"))
  13. #endif
  14. //_tcsrchr() 反向搜索获得最后一个'\\'的位置,并返回该位置的指针
  15. TCHAR *pFind = _tcsrchr(tcExePath, '\\');
  16. if (pFind == NULL)
  17. {
  18. return;
  19. }
  20. *pFind = '\0';
  21.  
  22. CString szIniPath = tcExePath;
  23. szIniPath += "\\";
  24. szIniPath += CONFIG_FILE;
  25.  
  26. //--------------------------------------------------------
  27. //BOOL WritePrivateProfileString(
  28. // LPCTSTR lpAppName, //节的名字,是一个以0结束的字符串
  29. // LPCTSTR lpKeyName, //键的名字,是一个以0结束的字符串。若为NULL,则删除整个节
  30. // LPCTSTR lpString, //键的值,是一个以0结束的字符串。若为NULL,则删除对应的键
  31. // LPCTSTR lpFileName //要写入的文件的文件名。若该ini文件与程序在同一个目录下,
  32. // ) 也可使用相对路径,否则需要给出绝度路径。
  33. //如果Ini不存在,它会自动在szIniPath上创建此INI文件.再执行写入.
  34. ::WritePrivateProfileString(TEXT("Service"), TEXT("Name"), TEXT("AutoRun Helper"), szIniPath);
  35. ::WritePrivateProfileString(TEXT("Service"), TEXT("Description"), TEXT("200"), szIniPath);
  36.  
  37. ::WritePrivateProfileString(TEXT("Registry"), TEXT("ServiceRootKey"), TEXT("Software\\AutoRun Modem Service"), szIniPath);
  38. ::WritePrivateProfileString(TEXT("Registry"), TEXT("ApplicationRootKey"), TEXT("Software\\Sepang\\AutoRun Modem"), szIniPath);
  39. ::WritePrivateProfileString(TEXT("Registry"), TEXT("ApplicationRootKey64"), TEXT("Software\\Wow6432Node\\Sepang\\AutoRun Modem"), szIniPath);
  40.  
  41. //这个说明不同节之中可以存在完全相同的键.
  42. ::WritePrivateProfileString(TEXT("Service"), TEXT("ApplicationRootKey64"), TEXT("Software\\Wow6432Node\\Sepang\\AutoRun Modem"), szIniPath);
  43.  
  44.  
  45. //下面执行读取 ----------------------------------
  46. if (!::PathFileExists(szIniPath))
  47. {
  48. return;
  49. }
  50.  
  51. TCHAR szKeyValue[MAX_PATH] = {0};
  52. int nValue = 0;
  53.  
  54. //--------------------------------------------------------
  55. //DWORD GetPrivateProfileString(
  56. // LPCTSTR lpAppName, // 节名
  57. // LPCTSTR lpKeyName, // 键名,读取该键的值
  58. // LPCTSTR lpDefault, // 若指定的键不存在,该值作为读取的默认值
  59. // LPTSTR lpReturnedString, // 一个指向缓冲区的指针,接收读取的字符串
  60. // DWORD nSize, // 指定lpReturnedString指向的缓冲区的大小
  61. // LPCTSTR lpFileName // 读取信息的文件名。若该ini文件与程序在同一个目录下,
  62. // 也可使用相对路径,否则需要给出绝度路径
  63. //UINT GetPrivateProfileInt(
  64. // LPCTSTR lpAppName, // 节名
  65. // LPCTSTR lpKeyName, // 键名,读取该键的值
  66. // INT nDefault, // 若指定的键名不存在,该值作为读取的默认值
  67. // LPCTSTR lpFileName // 同上
  68. //
  69. //--------------------------------------------------------
  70.  
  71. ::GetPrivateProfileString(TEXT("Service"), TEXT("Name"), NULL, szKeyValue, MAX_PATH, szIniPath);
  72. nValue = ::GetPrivateProfileInt(TEXT("Service"), TEXT("Description"), 0, szIniPath);
  73.  
  74.  
  75. }
void XXXXX::OnBnClickedWriteIniBtn()
{
// ----------------------------------------
// 模拟写入一个config.ini
// ----------------------------------------

// 得到exe执行路径.
TCHAR tcExePath[MAX_PATH] = {0};
::GetModuleFileName(NULL, tcExePath, MAX_PATH);
// 设置ini路径到exe同一目录下
#ifndef CONFIG_FILE
#define CONFIG_FILE(TEXT("Config1.ini"))
#endif
//_tcsrchr() 反向搜索获得最后一个'\\'的位置,并返回该位置的指针
TCHAR *pFind = _tcsrchr(tcExePath, '\\');
if (pFind == NULL)
{
return;
}
*pFind = '\0';
  
  CString szIniPath = tcExePath;
szIniPath += "\\";
szIniPath += CONFIG_FILE;

//--------------------------------------------------------
//BOOL WritePrivateProfileString(
//               LPCTSTR lpAppName,   //节的名字,是一个以0结束的字符串
//              LPCTSTR lpKeyName,   //键的名字,是一个以0结束的字符串。若为NULL,则删除整个节
//              LPCTSTR lpString,    //键的值,是一个以0结束的字符串。若为NULL,则删除对应的键
//              LPCTSTR lpFileName   //要写入的文件的文件名。若该ini文件与程序在同一个目录下,
  //               )             也可使用相对路径,否则需要给出绝度路径。
//如果Ini不存在,它会自动在szIniPath上创建此INI文件.再执行写入.              
  ::WritePrivateProfileString(TEXT("Service"), TEXT("Name"), TEXT("AutoRun Helper"), szIniPath);
::WritePrivateProfileString(TEXT("Service"), TEXT("Description"), TEXT("200"), szIniPath);

::WritePrivateProfileString(TEXT("Registry"), TEXT("ServiceRootKey"), TEXT("Software\\AutoRun Modem Service"), szIniPath);
::WritePrivateProfileString(TEXT("Registry"), TEXT("ApplicationRootKey"), TEXT("Software\\Sepang\\AutoRun Modem"), szIniPath);
  ::WritePrivateProfileString(TEXT("Registry"), TEXT("ApplicationRootKey64"), TEXT("Software\\Wow6432Node\\Sepang\\AutoRun Modem"), szIniPath);

//这个说明不同节之中可以存在完全相同的键.
  ::WritePrivateProfileString(TEXT("Service"), TEXT("ApplicationRootKey64"), TEXT("Software\\Wow6432Node\\Sepang\\AutoRun Modem"), szIniPath);


  //下面执行读取 ----------------------------------
if (!::PathFileExists(szIniPath))
{
return;
}

TCHAR szKeyValue[MAX_PATH] = {0};
int nValue = 0;

//--------------------------------------------------------
//DWORD GetPrivateProfileString(
//               LPCTSTR lpAppName,      // 节名
//               LPCTSTR lpKeyName,      // 键名,读取该键的值
//              LPCTSTR lpDefault,      // 若指定的键不存在,该值作为读取的默认值
//               LPTSTR lpReturnedString,   // 一个指向缓冲区的指针,接收读取的字符串
//              DWORD nSize,         // 指定lpReturnedString指向的缓冲区的大小
//               LPCTSTR lpFileName      // 读取信息的文件名。若该ini文件与程序在同一个目录下,
//                                也可使用相对路径,否则需要给出绝度路径
//UINT GetPrivateProfileInt(
//               LPCTSTR lpAppName,      // 节名
//               LPCTSTR lpKeyName,      // 键名,读取该键的值
//             INT nDefault,         // 若指定的键名不存在,该值作为读取的默认值
//              LPCTSTR lpFileName      // 同上
//
//--------------------------------------------------------

::GetPrivateProfileString(TEXT("Service"), TEXT("Name"), NULL, szKeyValue, MAX_PATH, szIniPath);
nValue = ::GetPrivateProfileInt(TEXT("Service"), TEXT("Description"), 0, szIniPath);


}

4.


四、如何判断一个ini文件中有多少个节

要判断一个ini文件中有多少个节,最简单的办法就是将所有的节名都找出来,然后统计节名的个数。而要将所有的节名找出来,使用GetPrivateProfileSectionNames函数就可以了,其原型如下:

DWORDGetPrivateProfileSectionNames(

LPTSTR lpszReturnBuffer, // 指向一个缓冲区,用来保存返回的所有节名。

DWORD nSize, // 参数lpszReturnBuffer的大校

LPCTSTR lpFileName // 文件名,若该ini文件与程序在同一个目录下,

// 也可使用相对路径,否则需要给出绝度路径。

)

下面的是用来统计一个ini文件中共有多少个节的函数,当然,如果需要同时找到每个节中的各个键及其值,根据找到节名就可以很容易的得到了。

/* 统计共有多少个节

节名的分离方法:若chSectionNames数组的第一字符是'\0'字符,则表明有0个节。

否则,从chSectionNames数组的第一个字符开始,顺序往后找,直到找到一个'\0'字符,

若该字符的后继字符不是'\0'字符,则表明前面的字符组成一个节名。

若连续找到两个'\0'字符,则统计结束。 */

  1. TCHAR chSectionNames[2048] = {0};
  2. TCHAR *pSectionName; // 保存找到的某个节名字符串的首地址。
  3. int j=0; // j用来保存下一个节名字符串的首地址相对于当前i的位置偏移量。
  4. int count = 0; // 统计节的个数。
  5.  
  6. ::GetPrivateProfileSectionNames(chSectionNames, 2048, szIniPath);
  7. for (i=0; i<2048; i++, j++)
  8. {
  9. if (chSectionNames[0] == '\0')
  10. {
  11. break; // 如果第一个字符就是0,则说明ini中一个节也没有。
  12. }
  13.  
  14. if (chSectionNames[i] == '\0')
  15. {
  16. // 找到一个’\0’,则说明从这个字符往前,减掉j个偏移量,就是一个节名的首地址。
  17. pSectionName = &chSectionNames[i-j];
  18. // 找到一个节名后,j的值要还原,以统计下一个节名地址的偏移量。
  19. // 赋成-1是因为节名字符串的最后一个字符’\0’是终止符,不能作为节名的一部分。
  20. j = -1;
  21.  
  22. // 在获取节名的时候可以获取该节中键的值,前提是我们知道该节中有哪些键。
  23. AfxMessageBox(pSectionName); // 把找到的显示出来。
  24.  
  25. if (chSectionNames[i+1] == 0) //is 0 or ‘\0’?
  26. {
  27. break; // 当两个相邻的字符都是0时,则所有的节名都已找到,循环终止。
  28. }
  29. }
  30. }