一个简易的配置类及其实现

配置文件基本格式:

//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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值