配置文件基本格式:
//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