配置文件基本格式:
//test.ini
[hello]
name = zhangsan
sex = M
[world]
//this is a comment
key = value
配置文件由
段名:如,hello等
鍵名:如,name等
值,如,zhangsan等構成
其中"="左右爲製表符分隔
由"//"打頭的註釋單獨佔一行
1.類框架基本思想://以下省略std::xxxxx
將文件按行讀入一個vetor<string>,遇到eof則終止。
用for_each()對每個string解析,其中解析由仿函數完成
在仿函數中解析string並構建map,如果有"["、"]"則兩者中間是段名sect
有"="則該string有具體的key,value,將其解析出來,按sect + “***" + key作爲map的key,value作爲map的value構建map,這樣不同的段中就可以有相同的key。
查找的時候則在map中檢索。
2.具體的:
CIniFile類基本接口:
bool open(const char *inipath); //打開一個配置文件
string read(const char *sect,const char *key); //根據段名,鍵查找值
void write(const char *sect,const char *key,const char *value); //添加配置,如果有該段則插入到該段下的第一個位置,如果有 該key則改變value,沒有則新建段,key插入到文件最後
void showall(); //顯示所有配置信息
void save(); //保存
仿函數由一個struct 重載operator()形成
3.具體代碼
//CIniFile.h
/********************************************************************
filename: CIniFile.h
date: 2011/1/27 16:13
author: wangcheng
purpose:
*********************************************************************/
#ifndef _INIFILE_H_
#define _INIFILE_H_
#include <map>
#include <list>
#include <string>
#include <algorithm>
#include <functional>
#include <fstream>
using namespace std;
typedef map<string,string,less<string> > strMap;
typedef strMap::iterator strMapit;
typedef list<string>::iterator strListit;
const char* const MIDDLESTRING = "***";
class CIniFile
{
public:
CIniFile();
~CIniFile();
bool open(const char *pinipath);
string read(const char *psect,const char *pkey);
void write(const string sect,const string key,const string value);
void showall();
void save();
protected:
bool do_open(const char *pinipath);
string m_inipath;
strMap m_inimap;
list<string> m_strlist;
};
struct AnalyzeIni
{
string strsect;
strMap *pmap;
AnalyzeIni(strMap &strmap);
void operator()(const string &strini);
};
#endif
//CIniFile.cpp
#include "CIniFile.h"
#include <iostream>
CIniFile::CIniFile()
{
}
CIniFile::~CIniFile()
{
}
bool CIniFile::open(const char *pinipath)
{
m_inipath = pinipath;
return do_open(pinipath);
}
string CIniFile::read(const char *psect,const char *pkey)
{
string mapkey = psect;
mapkey += MIDDLESTRING;
mapkey += pkey;
strMapit it = m_inimap.find(mapkey);
if(it == m_inimap.end())
{
return "";
}
else
{
return it->second;
}
}
void CIniFile::write(const string sect,const string key,const string value)
{
strMapit mapit = m_inimap.find(sect + MIDDLESTRING + key);
if(mapit != m_inimap.end())
{
mapit->second = value;
}
bool havedsect = false;
strListit it = m_strlist.begin();
strListit itend = m_strlist.end();
string secttmp = "[" + sect + "]";
string keytmp = key + "/t=/t" + value;
for( ;it != itend; ++it)
{
if(*it == secttmp)
{
havedsect = true;
}
if((*it).find(key + "/t=/t") != string::npos)
{
*it = keytmp;
save();
return;
}
}
if(havedsect)
{
m_strlist.insert(++it,keytmp);
}
else
{
m_strlist.push_back(secttmp);
m_strlist.push_back(keytmp);
}
save();
}
void CIniFile::save()
{
ofstream of;
of.open(m_inipath.c_str());
strListit it,itend;
if(of.is_open())
{
it = m_strlist.begin();
itend = m_strlist.end();
--itend;
for( ;it != itend; ++it)
{
of << *it + "/n";
}
of << *it;
}
of.close();
}
void CIniFile::showall()
{
ifstream fin;
fin.open(m_inipath.c_str());
while(!fin.eof())
{
string inbuff;
getline(fin,inbuff,'/n');
cout << inbuff << endl;
}
fin.close();
}
bool CIniFile::do_open(const char *pinipath)
{
ifstream fin;
fin.open(pinipath);
if(!fin.is_open())
{
fin.close();
return false;
}
while(!fin.eof())
{
string inbuff;
getline(fin,inbuff,'/n');
if(inbuff.size())
{
m_strlist.push_back(inbuff);
}
}
if(m_strlist.empty())
return false;
for_each(m_strlist.begin(),m_strlist.end(),AnalyzeIni(m_inimap));
fin.close();
}
//仿函數
AnalyzeIni::AnalyzeIni(strMap &strmap) : pmap(&strmap)
{
}
void AnalyzeIni::operator()(const string &strini)
{
bool iscomment = !(strini.find("//") == string::npos);
if(iscomment)
return;
size_t first = strini.find('[');
size_t last = strini.find(']');
if(first != string::npos && last != string::npos && first != last + 1)
{
strsect = strini.substr(first + 1,last - first - 1);
return;
}
if(strsect.empty())
return;
if((first = strini.find('=')) == string::npos)
return;
//key
string strtmp1 = strini.substr(0,first);
//value
string strtmp2 = strini.substr(first + 1);
//key
first = strtmp1.find_first_not_of("/t");
last = strtmp1.find_last_not_of("/t");
if(first == string::npos || last == string::npos)
return;
string strkey = strtmp1.substr(first,last - first + 1);
//value
first = strtmp2.find_first_not_of("/t");
last = strtmp2.find_last_not_of("/t");
if(first == string::npos || last == string::npos)
return;
string value = strtmp2.substr(first,last - first + 1);
string mapkey = strsect + MIDDLESTRING;
mapkey += strkey;
(*pmap)[mapkey] = value;
return;
}
//測試程序 main.cpp
#include "CIniFile.h"
#include <iostream>
int main()
{
CIniFile inifile;
if(inifile.open("test.ini"))
{
// cout << inifile.read("hello","myname") << endl;
cout << "this is now for read,please enter the sect end key" << endl;
string sect,key;
cin >> sect >> key;
cout << inifile.read(sect.c_str(),key.c_str()) << endl;
string value;
cout << "this is now for write,please enter the sect,key and value" << endl;
cin >> sect >> key >> value;
inifile.write(sect,key,value);
}
else
{
cout << "open failed!" << endl;
}
inifile.showall();
return 0;
}
//配置文件 test.ini
//hello linux!
[hello]
//hello linux!
myname = wangcheng
[world]
myname = hakakaj
yourname = zhangsan
[linux]
daddy = 233hajdh
[redflag]
family = 100
[love]
make = 3
編譯、執行
g++ main.cpp CIniFile.h CIniFile.cpp -o main
./main