C++針對ini配置檔案讀寫大全
ini檔案(Initialization file),這種型別的檔案中通常存放的是一個程式的初始化資訊。ini檔案由若干個節(Section)組成,每個Section由若干鍵(Key)組成,每個Key可以賦相應的值。讀寫ini檔案實際上就是讀寫某個的Section中相應的Key的值,而這隻要藉助幾個函式即可完成。
1. 把資訊寫入系統的win.ini檔案
[cpp] view plaincopyprint?- BOOL WriteProfileString(
- LPCTSTR lpAppName, // 節的名字,是一個以0結束的字串
- LPCTSTR lpKeyName, // 鍵的名字,是一個以0結束的字串。若為NULL,則刪除整個節
- LPCTSTR lpString // 鍵的值,是一個以0結束的字串。若為NULL,則刪除對應的鍵
- )
BOOL WriteProfileString(
LPCTSTR lpAppName, // 節的名字,是一個以0結束的字串
LPCTSTR lpKeyName, // 鍵的名字,是一個以0結束的字串。若為NULL,則刪除整個節
LPCTSTR lpString // 鍵的值,是一個以0結束的字串。若為NULL,則刪除對應的鍵
)
2、從系統的win.ini檔案中讀取資訊
[cpp] view plaincopyprint?- DWORD
- LPCTSTR lpAppName, // 節名
- LPCTSTR lpKeyName, // 鍵名,讀取該鍵的值
- LPCTSTR lpDefault, // 若指定的鍵不存在,該值作為讀取的預設值
- LPTSTR lpReturnedString, // 一個指向緩衝區的指標,接收讀取的字串
- DWORD nSize // 指定lpReturnedString指向的緩衝區的大小
- )
[cpp] view plaincopyprint?DWORD GetProfileString( LPCTSTR lpAppName, // 節名 LPCTSTR lpKeyName, // 鍵名,讀取該鍵的值 LPCTSTR lpDefault, // 若指定的鍵不存在,該值作為讀取的預設值 LPTSTR lpReturnedString, // 一個指向緩衝區的指標,接收讀取的字串 DWORD nSize // 指定lpReturnedString指向的緩衝區的大小 )
- UINT GetProfileInt(
- LPCTSTR lpAppName, // 同上
- LPCTSTR lpKeyName, // 同上
- INT nDefault // 若指定的鍵名不存在,該值作為讀取的預設值
- )
UINT GetProfileInt(
LPCTSTR lpAppName, // 同上
LPCTSTR lpKeyName, // 同上
INT nDefault // 若指定的鍵名不存在,該值作為讀取的預設值
)
3.寫入讀取自己的ini
簡單的INI例子:
[html] view plaincopyprint?- [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
[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
下面示例顯示它是如何生成的:
- 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);
- }
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?- TCHAR chSectionNames[2048] = {0};
- TCHAR *pSectionName; // 儲存找到的某個節名字串的首地址。
- int j=0; // j用來儲存下一個節名字串的首地址相對於當前i的位置偏移量。
- int count = 0; // 統計節的個數。
- ::GetPrivateProfileSectionNames(chSectionNames, 2048, szIniPath);
- for (i=0; i<2048; i++, j++)
- {
- if (chSectionNames[0] == '\0')
- {
- break; // 如果第一個字元就是0,則說明ini中一個節也沒有。
- }
- if (chSectionNames[i] == '\0')
- {
- // 找到一個’\0’,則說明從這個字元往前,減掉j個偏移量,就是一個節名的首地址。
- pSectionName = &chSectionNames[i-j];
- // 找到一個節名後,j的值要還原,以統計下一個節名地址的偏移量。
- // 賦成-1是因為節名字串的最後一個字元’\0’是終止符,不能作為節名的一部分。
- j = -1;
- // 在獲取節名的時候可以獲取該節中鍵的值,前提是我們知道該節中有哪些鍵。
- AfxMessageBox(pSectionName); // 把找到的顯示出來。
- if (chSectionNames[i+1] == 0) //is 0 or ‘\0’?
- {
- break; // 當兩個相鄰的字元都是0時,則所有的節名都已找到,迴圈終止。
- }
- }
- }