1. 程式人生 > >C++針對ini配置檔案讀寫大全

C++針對ini配置檔案讀寫大全

ini檔案(Initialization file),這種型別的檔案中通常存放的是一個程式的初始化資訊。ini檔案由若干個節(Section)組成,每個Section由若干鍵(Key)組成,每個Key可以賦相應的值。讀寫ini檔案實際上就是讀寫某個的Section中相應的Key的值,而這隻要藉助幾個函式即可完成。

1. 把資訊寫入系統的win.ini檔案

[cpp] view plaincopyprint?
  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檔案中讀取資訊

[cpp] view plaincopyprint?
  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指向的緩衝區的大小
)
[cpp] view plaincopyprint?
  1. UINT GetProfileInt(  
  2. LPCTSTR lpAppName,            // 同上  
  3. LPCTSTR lpKeyName,             // 同上  
  4. INT nDefault                             // 若指定的鍵名不存在,該值作為讀取的預設值  
  5. )  
UINT GetProfileInt(
LPCTSTR lpAppName,            // 同上
LPCTSTR lpKeyName,             // 同上
INT nDefault                             // 若指定的鍵名不存在,該值作為讀取的預設值
)

3.寫入讀取自己的ini

簡單的INI例子:

[html] view plaincopyprint?
  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


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

[cpp] view plaincopyprint?
  1. void XXXXX::OnBnClickedWriteIniBtn()  
  2. {  
  3.     // ----------------------------------------  
  4.     // 模擬寫入一個config.ini  
  5.     // ----------------------------------------  
  6.     // 得到exe執行路徑.  
  7.     TCHAR tcExePath[MAX_PATH] = {0};  
  8.     ::GetModuleFileName(NULL, tcExePath, MAX_PATH);  
  9.     // 設定ini路徑到exe同一目錄下  
  10. #ifndef CONFIG_FILE  
  11. #define CONFIG_FILE     (TEXT("Config1.ini"))  
  12. #endif  
  13.     //_tcsrchr() 反向搜尋獲得最後一個'\\'的位置,並返回該位置的指標  
  14.     TCHAR *pFind = _tcsrchr(tcExePath, '\\');  
  15.     if (pFind == NULL)  
  16.     {  
  17.         return;  
  18.     }  
  19.     *pFind = '\0';  
  20.     CString szIniPath = tcExePath;  
  21.     szIniPath += "\\";  
  22.     szIniPath += CONFIG_FILE;  
  23.     //--------------------------------------------------------  
  24.     //BOOL WritePrivateProfileString(  
  25.     //                              LPCTSTR lpAppName,      //節的名字,是一個以0結束的字串  
  26.     //                              LPCTSTR lpKeyName,      //鍵的名字,是一個以0結束的字串。若為NULL,則刪除整個節  
  27.     //                              LPCTSTR lpString,       //鍵的值,是一個以0結束的字串。若為NULL,則刪除對應的鍵  
  28.     //                              LPCTSTR lpFileName      //要寫入的檔案的檔名。若該ini檔案與程式在同一個目錄下,  
  29.     //                              )                          也可使用相對路徑,否則需要給出絕度路徑。  
  30.     //如果Ini不存在,它會自動在szIniPath上建立此INI檔案.再執行寫入.                             
  31.     ::WritePrivateProfileString(TEXT("Service"), TEXT("Name"), TEXT("AutoRun  Helper"), szIniPath);  
  32.     ::WritePrivateProfileString(TEXT("Service"), TEXT("Description"), TEXT("200"), szIniPath);  
  33.     ::WritePrivateProfileString(TEXT("Registry"), TEXT("ServiceRootKey"), TEXT("Software\\AutoRun Modem Service"), szIniPath);  
  34.     ::WritePrivateProfileString(TEXT("Registry"), TEXT("ApplicationRootKey"), TEXT("Software\\Sepang\\AutoRun Modem"), szIniPath);  
  35.     ::WritePrivateProfileString(TEXT("Registry"), TEXT("ApplicationRootKey64"), TEXT("Software\\Wow6432Node\\Sepang\\AutoRun Modem"), szIniPath);  
  36.     //這個說明不同節之中可以存在完全相同的鍵.  
  37.     ::WritePrivateProfileString(TEXT("Service"), TEXT("ApplicationRootKey64"), TEXT("Software\\Wow6432Node\\Sepang\\AutoRun Modem"), szIniPath);  
  38.     //下面執行讀取 ----------------------------------  
  39.     if (!::PathFileExists(szIniPath))  
  40.     {  
  41.         return;  
  42.     }  
  43.     TCHAR szKeyValue[MAX_PATH] = {0};  
  44.     int nValue = 0;  
  45.     //--------------------------------------------------------  
  46.     //DWORD GetPrivateProfileString(  
  47.     //                              LPCTSTR lpAppName,            // 節名  
  48.     //                              LPCTSTR lpKeyName,            // 鍵名,讀取該鍵的值  
  49.     //                              LPCTSTR lpDefault,            // 若指定的鍵不存在,該值作為讀取的預設值  
  50.     //                              LPTSTR lpReturnedString,      // 一個指向緩衝區的指標,接收讀取的字串  
  51.     //                              DWORD nSize,                  // 指定lpReturnedString指向的緩衝區的大小  
  52.     //                              LPCTSTR lpFileName            // 讀取資訊的檔名。若該ini檔案與程式在同一個目錄下,  
  53.     //                                                                也可使用相對路徑,否則需要給出絕度路徑  
  54.     //UINT GetPrivateProfileInt(  
  55.     //                              LPCTSTR lpAppName,            // 節名  
  56.     //                              LPCTSTR lpKeyName,            // 鍵名,讀取該鍵的值  
  57.     //                              INT nDefault,                 // 若指定的鍵名不存在,該值作為讀取的預設值  
  58.     //                              LPCTSTR lpFileName            // 同上  
  59.     //  
  60.     //--------------------------------------------------------  
  61.     ::GetPrivateProfileString(TEXT("Service"), TEXT("Name"), NULL, szKeyValue, MAX_PATH, szIniPath);  
  62.     nValue = ::GetPrivateProfileInt(TEXT("Service"), TEXT("Description"), 0, szIniPath);  
  63. }  
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'字元,則統計結束。 */

[cpp] view plaincopyprint?
  1. TCHAR chSectionNames[2048] = {0};    
  2.     TCHAR *pSectionName;   // 儲存找到的某個節名字串的首地址。  
  3.     int j=0;               // j用來儲存下一個節名字串的首地址相對於當前i的位置偏移量。  
  4.     int count = 0;         // 統計節的個數。  
  5.     ::GetPrivateProfileSectionNames(chSectionNames, 2048, szIniPath);  
  6.     for (i=0; i<2048; i++, j++)  
  7.     {  
  8.         if (chSectionNames[0] == '\0')  
  9.         {  
  10.             break;       // 如果第一個字元就是0,則說明ini中一個節也沒有。  
  11.         }  
  12.         if (chSectionNames[i] == '\0')  
  13.         {  
  14.             // 找到一個’\0’,則說明從這個字元往前,減掉j個偏移量,就是一個節名的首地址。  
  15.             pSectionName = &chSectionNames[i-j];   
  16.             // 找到一個節名後,j的值要還原,以統計下一個節名地址的偏移量。  
  17.             // 賦成-1是因為節名字串的最後一個字元’\0’是終止符,不能作為節名的一部分。  
  18.             j = -1;  
  19.             // 在獲取節名的時候可以獲取該節中鍵的值,前提是我們知道該節中有哪些鍵。  
  20.             AfxMessageBox(pSectionName);   // 把找到的顯示出來。  
  21.             if (chSectionNames[i+1] == 0)   //is 0 or ‘\0’?  
  22.             {  
  23.                 break;  // 當兩個相鄰的字元都是0時,則所有的節名都已找到,迴圈終止。  
  24.             }  
  25.         }  
  26.     }