一個簡易的配置類及其實現

配置文件基本格式:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章