C/C++ INI檔案操作實現程式碼
一、INI檔案用途:
1、儲存程式的初始化資訊;
2、儲存需要儲存的資料資訊。
二、INI檔案結構:
由節名、鍵名、鍵值組成。形式如下:
[節名]
鍵名 = 鍵值
備註:一個INI檔案,可以用多個節。
三、讀取INI檔案
1、WritePrivateProfileString
該函式用於向INI檔案中寫入一個字串資料。
函式原型如下:
BOOL WritePrivateProfileString( LPCTSTR lpAppName,// pointer to section name LPCTSTR lpKeyName,// pointer to key name LPCTSTR lpString,// pointer to string to add LPCTSTR lpFileName // pointer to initialization filename );
引數說明:
lpAppName:指定節名,以空終止結尾的字串。如果INI檔案中節名不存在,將建立一個節名。
lpKeyName:鍵名,以空終止結尾的字串。如果INI檔案中該鍵名不存在,將建立一個鍵名。如果該引數為NULL,包括節及節下的所有專案都將被刪除。
lpString:寫到鍵值中的資料,以空終止結尾的字串。
lpFileName:INI檔案的名稱,以空終止結尾的字串。指定需要寫入資料的INI檔案,如果指定的INI檔案不存在將建立。
返回值:
如果函式成功將字串複製到初始化檔案,返回值是非零。
如果函式失敗,重新整理快取版本的最近訪問初始化檔案,返回值是零。
2、GetPrivateProfileString
該函式用於獲取INI檔案中的鍵值。
函式原型如下:
DWORD GetPrivateProfileString( LPCTSTR lpAppName,// points to section name LPCTSTR lpKeyName,// points to key name LPCTSTR lpDefault,// points to default string LPTSTR lpReturnedString,// points to destination buffer DWORD nSize,// size of destination buffer LPCTSTR lpFileName // points to initialization filename );
引數說明:
lpAppName:指定節名,以空終止結尾的字串。如果該引數為NULL,函式將複製所有的節名到所指定的緩衝區中。
lpKeyName:鍵名,以空終止結尾的字串。如果該引數為NULL,函式將lpAppName節下所有的鍵名複製到lpReturnedString緩衝區。
lpDefault:預設值,以空終止結尾的字串。如果獲取鍵值的鍵名不存在時,返回設定的預設值。
lpReturnedString:用於接受資料的緩衝區。
nSize:以字元為單位表示lpReturnedString緩衝區的大小。
lpFileName:INI檔名稱,以空終止結尾的字串。
返回值:
返回值是字元複製到緩衝區的數量,不包括終止null字元。
3、GetPrivateProfileInt
該函式用於從INI檔案中獲取整型資料。
函式原型如下:
UINT GetPrivateProfileInt( LPCTSTR lpAppName,// address of section name LPCTSTR lpKeyName,// address of key name INT nDefault,// return value if key name is not found LPCTSTR lpFileName // address of initialization filename );
引數說明:
lpAppName:節名。
lpKeyName:鍵名。
nDefault:預設值。
lpFileName:INI檔名稱。
返回值:
函式返回實際讀取的整數值。
4、GetPrivateProfileSectionNames
該函式用於返回INI檔案中的所有節名。
函式原型如下:
DWORD GetPrivateProfileSectionNames( LPTSTR lpszReturnBuffer,// address of return buffer DWORD nSize,// size of return buffer LPCTSTR lpFileName // address of initialization filename );
引數說明:
lpszReturnBuffer:接受節名的資料緩衝區。
nSize:緩衝區的大小。
lpFileName:INI檔名稱。
返回值:
返回值指定數量的字元複製到指定的緩衝,不包括終止null字元。
如果緩衝區沒有大到足以包含所有相關的部分名稱指定的初始化檔案,返回值等於指定的長度nSize - 2。
5、GetPrivateProfileSection
該函式用於獲取指定節下的所有的鍵名和鍵值。
函式原型如下:
DWORD GetPrivateProfileSection( LPCTSTR lpAppName,// address of section name LPTSTR lpReturnedString,// size of return buffer LPCTSTR lpFileName // address of initialization filename );
引數說明:
lpAppName:節名。
lpReturnedString:用於接受資料的緩衝區。
nSize:緩衝區的大小。
lpFileName:INI檔名稱。
返回值:
返回值指定數量的字元複製到緩衝區,不包括終止null字元。
如果緩衝區沒有大到足以包含所有與指定相關聯的鍵名稱和值對部分,返回值等於nSize - 2。
四、C++實現INI檔案讀寫完整程式碼
CMyINI.h
#pragma once #include <iostream> #include <fstream> #include <sstream> #include <vector> #include <cstdlib> #include <map> using namespace std; //INI檔案結點儲存結構 class ININode { public: ININode(string root,string key,string value) { this->root = root; this->key = key; this->value = value; } string root; string key; string value; }; //鍵值對結構體 class SubNode { public: void InsertElement(string key,string value) { sub_node.insert(pair<string,string>(key,value)); } map<string,string> sub_node; }; //INI檔案操作類 class CMyINI { public: CMyINI(); ~CMyINI(); public: int ReadINI(string path); //讀取INI檔案 string GetValue(string root,string key); //由根結點和鍵獲取值 vector<ININode>::size_type GetSize(){ return map_ini.size(); } //獲取INI檔案的結點數 vector<ININode>::size_type SetValue(string root,string value); //設定根結點和鍵獲取值 int WriteINI(string path); //寫入INI檔案 void Clear(){ map_ini.clear(); } //清空 void Travel(); //遍歷列印INI檔案 private: map<string,SubNode> map_ini; //INI檔案內容的儲存變數 };
CMyINI.cpp
#include "StdAfx.h" #include "MyINI.h" #define INIDEBUG CMyINI::CMyINI() { } CMyINI::~CMyINI() { } //************************************************************************ // 函式名稱: TrimString // 訪問許可權: public // 建立日期: 2017/01/05 // 創 建 人: // 函式說明: 去除空格 // 函式引數: string & str 輸入的字串 // 返 回 值: std::string & 結果字串 //************************************************************************ string &TrimString(string &str) { string::size_type pos = 0; while (str.npos != (pos = str.find(" "))) str = str.replace(pos,pos + 1,""); return str; } //************************************************************************ // 函式名稱: ReadINI // 訪問許可權: public // 建立日期: 2017/01/05 // 創 建 人: // 函式說明: 讀取INI檔案,並將其儲存到map結構中 // 函式引數: string path INI檔案的路徑 // 返 回 值: int //************************************************************************ int CMyINI::ReadINI(string path) { ifstream in_conf_file(path.c_str()); if (!in_conf_file) return 0; string str_line = ""; string str_root = ""; vector<ININode> vec_ini; while (getline(in_conf_file,str_line)) { string::size_type left_pos = 0; string::size_type right_pos = 0; string::size_type equal_div_pos = 0; string str_key = ""; string str_value = ""; if ((str_line.npos != (left_pos = str_line.find("["))) && (str_line.npos != (right_pos = str_line.find("]")))) { //cout << str_line.substr(left_pos+1,right_pos-1) << endl; str_root = str_line.substr(left_pos + 1,right_pos - 1); } if (str_line.npos != (equal_div_pos = str_line.find("="))) { str_key = str_line.substr(0,equal_div_pos); str_value = str_line.substr(equal_div_pos + 1,str_line.size() - 1); str_key = TrimString(str_key); str_value = TrimString(str_value); //cout << str_key << "=" << str_value << endl; } if ((!str_root.empty()) && (!str_key.empty()) && (!str_value.empty())) { ININode ini_node(str_root,str_key,str_value); vec_ini.push_back(ini_node); //cout << vec_ini.size() << endl; } } in_conf_file.close(); in_conf_file.clear(); //vector convert to map map<string,string> map_tmp; for (vector<ININode>::iterator itr = vec_ini.begin(); itr != vec_ini.end(); ++itr) { map_tmp.insert(pair<string,string>(itr->root,"")); } //提取出根節點 for (map<string,string>::iterator itr = map_tmp.begin(); itr != map_tmp.end(); ++itr) { #ifdef INIDEBUG cout << "根節點: " << itr->first << endl; #endif //INIDEBUG SubNode sn; for (vector<ININode>::iterator sub_itr = vec_ini.begin(); sub_itr != vec_ini.end(); ++sub_itr) { if (sub_itr->root == itr->first) { #ifdef INIDEBUG cout << "鍵值對: " << sub_itr->key << "=" << sub_itr->value << endl; #endif //INIDEBUG sn.InsertElement(sub_itr->key,sub_itr->value); } } map_ini.insert(pair<string,SubNode>(itr->first,sn)); } return 1; } //************************************************************************ // 函式名稱: GetValue // 訪問許可權: public // 建立日期: 2017/01/05 // 創 建 人: // 函式說明: 根據給出的根結點和鍵值查詢配置項的值 // 函式引數: string root 配置項的根結點 // 函式引數: string key 配置項的鍵 // 返 回 值: std::string 配置項的值 //************************************************************************ string CMyINI::GetValue(string root,string key) { map<string,SubNode>::iterator itr = map_ini.find(root); map<string,string>::iterator sub_itr = itr->second.sub_node.find(key); if (!(sub_itr->second).empty()) return sub_itr->second; return ""; } //************************************************************************ // 函式名稱: WriteINI // 訪問許可權: public // 建立日期: 2017/01/05 // 創 建 人: // 函式說明: 儲存XML的資訊到檔案中 // 函式引數: string path INI檔案的儲存路徑 // 返 回 值: int //************************************************************************ int CMyINI::WriteINI(string path) { ofstream out_conf_file(path.c_str()); if (!out_conf_file) return -1; //cout << map_ini.size() << endl; for (map<string,SubNode>::iterator itr = map_ini.begin(); itr != map_ini.end(); ++itr) { //cout << itr->first << endl; out_conf_file << "[" << itr->first << "]" << endl; for (map<string,string>::iterator sub_itr = itr->second.sub_node.begin(); sub_itr != itr->second.sub_node.end(); ++sub_itr) { //cout << sub_itr->first << "=" << sub_itr->second << endl; out_conf_file << sub_itr->first << "=" << sub_itr->second << endl; } } out_conf_file.close(); out_conf_file.clear(); return 1; } //************************************************************************ // 函式名稱: SetValue // 訪問許可權: public // 建立日期: 2017/01/05 // 創 建 人: // 函式說明: 設定配置項的值 // 函式引數: string root 配置項的根節點 // 函式引數: string key 配置項的鍵 // 函式引數: string value 配置項的值 // 返 回 值: std::vector<ININode>::size_type //************************************************************************ vector<ININode>::size_type CMyINI::SetValue(string root,string value) { map<string,SubNode>::iterator itr = map_ini.find(root); //查詢 if (map_ini.end() != itr) { //itr->second.sub_node.insert(pair<string,value)); itr->second.sub_node[key] = value; } //根節點已經存在了,更新值 else { SubNode sn; sn.InsertElement(key,value); map_ini.insert(pair<string,SubNode>(root,sn)); } //根節點不存在,新增值 return map_ini.size(); } //************************************************************************ // 函式名稱: Travel // 訪問許可權: public // 建立日期: 2017/01/05 // 創 建 人: // 函式說明: 遍歷列印INI檔案 // 返 回 值: void //************************************************************************ void CMyINI::Travel() { for (map<string,SubNode>::iterator itr = this->map_ini.begin(); itr!= this->map_ini.end(); ++itr) { //root cout << "[" << itr->first << "]" << endl; for (map<string,string>::iterator itr1=itr->second.sub_node.begin(); itr1!=itr->second.sub_node.end(); ++itr1) { cout << " " << itr1->first << " = " << itr1->second << endl; } } }
測試之前INI檔案的內容:
測試程式:
CMyINI *p = new CMyINI(); p->ReadINI("Setting.ini"); cout << "\n原始INI檔案內容:" << std::endl; p->Travel(); p->SetValue("setting","hehe","eheh"); cout << "\n增加節點之後的內容:" << std::endl; p->Travel(); cout << "\n修改節點之後的內容:" << std::endl; p->SetValue("kk","kk","2"); p->Travel(); p->WriteINI("Setting.ini");
測試結果:
五、C++讀寫ini檔案中的配置資訊
ini檔案是由若干個節(Sction)組成,每個節又由若干個鍵(Key)組成。
1、將檔案寫入ini檔案中,主要使用的函式是WritePrivateProfileString(LPCWSTR IpAppName,LPCWSTR IpKeyName,LPCWSTR IpString,LPCWSTR IpFileName);
引數一表示節的名字,引數二表示鍵的名字,若為NULL,則刪除整個節,引數三表示鍵的值,若為NULL,則刪除這個鍵,引數四表示檔名。
#ifndef CONFIG_FILE
#define CONFIG_FILE (_T("Config.ini"))
#endif
TCHAR IniPath[MAX_PATH]={0}
GetModuleFileName(NULL,IniPath,Max_Path);
TCHAR *pFind=_tcsrchr(IniPath,'\\');
if(pFind==NULL)
{
return;
}
*pFind='\0';
CString newIniPath=IniPath;
newIniPath+="\\";
newIniPath+=CONFIG_FILE;
寫入........
2、將ini檔案中的配置資訊讀取出來,主要使用的函式為GetPrivateProfileString(LPCWSTR IpAppName,LPCWSTR IpKeyName,LPCWSTR IpDefault,LPCWSTR IpReturnedString,DWORD nSize,LPCWSTR IpFileName)和GetPrivateProfileInt(LPCWSTR IpAppName,LPCWSTR IpKeyName,Int nDefault,LPCWSTR IpFileName);
GetPrivateProfileString:引數一表示節的名字,引數二表示鍵的名字,引數三表示如果指定的鍵名不存在時所預設的讀取值,引數四用來接收讀取的字串,引數五指定lpReturnedString指向的緩衝區的大小 ,引數六表示檔名。
GetPrivateProfileInt:引數一表示節的名字,引數二表示鍵的名字,引數三表示如果指定的鍵名不存在時所預設的讀取值,引數四表示檔名。
TCHAR IniPath[MAX_PATH]={0};
GetModuleFileName(NULL,Max_Path);
IniPath[_tcslen(IniPath)-1]='i'
IniPath[_tcslen(IniPath)-2]='n'
IniPath[_tcslen(IniPath)-3]='i'
if(!PathFileExists(IniPath))
{}
讀取...........