INI配置文件类

        工作中需要经常读取INI配置文件,自己写了一个简单的类来做这些重复工作,该类简单实用,在我的工作中发挥了较好效用,下面贴出代码,供有需要的人参考。

CommonDefs.h文件

//=============================================================================
/**
*  @file    CommonDefs.h
*
*  $Id: CommonDefs.h version 1.0 2007-11-20 $
*
*  @author Zhao Jun <zjwaszx@gmail.com>
*
*  Copyright (c) 2008 by <ZhaoJun>
*/
//=============================================================================

#ifndef __COMMOM_DEFS_H__
#define __COMMOM_DEFS_H__

 


///
/// 名字空间宏声明
///

#ifdef HAVE_LTK_NAMESPACE
namespace NS_Lightweight_ToolKit
{
}

namespace LTK = NS_Lightweight_ToolKit;

/// 名字空间开始宏声明
# define __LTK_BEGIN namespace NS_Lightweight_ToolKit {

/// 名字空间结束宏声明
# define __LTK_END }

/// 使用名字空间宏声明
# define __USE_NS_LTK using namespace NS_Lightweight_ToolKit;
#else
# define __LTK_BEGIN
# define __LTK_END
# define __USE_NS_LTK
#endif


/// 定义内联函数关键字
#define INLINE inline

 


__LTK_BEGIN

///
/// 常量定义
///

/// 一行的最大字节数
static const int MAX_LINE_BYTE = 2048;

 

///
/// 函数返回值类型定义
///

/// 定义函数返回代码类型
typedef int RET_CODE;

/// 函数成功返回代码
static const RET_CODE RET_CODE_OK = 0;

/// 函数失败返回代码
static const RET_CODE RET_CODE_ERR = -1;

 


__LTK_END

#endif // __COMMOM_DEFS_H__

 

IniProfile.h文件

//=============================================================================
/**
 *  @file    IniProfile.h
 *
 *  $Id: IniProfile.h version 1.0 2007-11-20 $
 *
 *  @author Zhao Jun <zjwaszx@gmail.com>
 *
 *  Copyright (c) 2008 by <ZhaoJun>
 */
//=============================================================================

#ifndef __INI_PROFILE_H__
#define __INI_PROFILE_H__

 

#include <vector>
#include <utility>
#include <iostream>
#include <fstream>
#include <string>
#include <map>

#include "CommonDefs.h"


__LTK_BEGIN


using std::vector;
using std::pair;
using std::cout;
using std::ifstream;
using std::string;
using std::map;
using std::endl;
using std::ofstream;

 


/**
 @brief 读取INI配置文件的类.

 一个专门用于读取INI配置文件的类.
*/
class CIniProfile
{
 /// INI配置文件的一个键值对.
 typedef pair<string, string> INI_ITEM;

 
 /// INI配置文件的一个配置段.  
 class CIniSection
 {
  friend class CIniProfile;
 public:
  string strSection;    ///< INI配置段名
  vector<INI_ITEM> vecSection; ///< INI配置项目对
 }; 

public:
 /// 默认构造函数.
 CIniProfile();

 
 /// 析构函数,什么也不做.
 ~CIniProfile();


 /**
  @brief 读取配置文件内容.
 
  @param strProfile, 配置文件路径
  @return bool,
      true  --读取成功
      false --读取失败
  */
 bool LoadConfig(const string &strProfile);
 

 /**
  @brief 获取配置文件中某一项的值.
 
  @param strSection, INI分段名
  @param strKey,  INI项目名
  @param strValue, 保存有INT值,输出
  @return bool,
      true --获取成功
      false --获取失败
  */
 bool GetItem(const string &strSection, const string &strKey, string &strValue);


 /**
  @brief 转换到XML文件格式.
 
  @param strXmlFilePath, 转换后的XML配置文件名
  */
 void ToXMLFormat(const string &strXmlFilePath);
 
protected:
 
 /**
  @brief 解析配置文件的一行内容.
  
  @return int,
      RET_CODE_OK --解析成功
      RET_CODE_ERR --解析失败
  */
 RET_CODE ParseLine(string strLine);


 /// 将字符串两边的空格和TAB去掉.
 string Trim(const string &strIn);

private:
 /// 配置文件路径
 string m_strProfile;
   
 /// 读取到的配置文件项目
 vector<CIniSection> m_iniSections; 

 /// 已读取的配置文件的行数
 int m_nLineCount;

 /// 调试函数,打印读取到的配置文件项目内容.
 void Dump();
};

__LTK_END


#include "impl/IniProfile_impl.h"

#endif // __INI_PROFILE_H__
 

 

IniProfile_impl.h文件
__LTK_BEGIN

INLINE
CIniProfile::CIniProfile()
{
 m_nLineCount = 0;
}


INLINE
CIniProfile::~CIniProfile()
{
}


INLINE
bool CIniProfile::LoadConfig(const string &strProfile)
{
 m_iniSections.clear();
 m_nLineCount = 0;
 m_strProfile = strProfile;

 char szLine[MAX_LINE_BYTE] = { 0 };
 ifstream ifs(m_strProfile.c_str()); 
 while (ifs.getline(szLine, MAX_LINE_BYTE, '/n'))
 {
  m_nLineCount++;
  string strLine(szLine);
  switch (ParseLine(strLine))
  {
  case RET_CODE_OK:
   break;
  case RET_CODE_ERR:
   cout<<"Profile Error at line "<<m_nLineCount<<" : "<<strLine<<endl;
   return false;
   break;  
  default:
   break;
  }
 }

 return true;
}


INLINE
bool CIniProfile::GetItem(const string &strSection, const string &strKey, string &strValue)
{
 for (vector<CIniSection>::iterator iter = m_iniSections.begin();
  iter != m_iniSections.end();
  ++iter)
 {
  if (iter->strSection == strSection)
  {
   for (vector<INI_ITEM>::iterator iniIter = iter->vecSection.begin();
    iniIter != iter->vecSection.end();
    ++iniIter)
   {
    if (iniIter->first == strKey)
    {
     strValue = iniIter->second;
     return true;
    }
   }
   return true;
  }
 }
 return false;
}


INLINE
void CIniProfile::Dump()
{
 for (vector<CIniSection>::iterator iter = m_iniSections.begin();
  iter != m_iniSections.end();
  ++iter)
 {
  cout<<'['<<iter->strSection<<"]/n";
  for (vector<INI_ITEM>::iterator iniIter = iter->vecSection.begin();
   iniIter != iter->vecSection.end();
   ++iniIter)
  {
   cout<<iniIter->first<<"="<<iniIter->second<<"/n";
  }
 } 
}


INLINE
RET_CODE CIniProfile::ParseLine(string strLine)
{
 static string strSectionName = "default";

 string::size_type nPos = 0;
 if (strLine[0] == '#')        // 注释
 {
  return RET_CODE_OK;
 }
 else if (strLine[0] == '[')       // 段落
 {   
  nPos = strLine.find(']', 1);
  if (nPos == string::npos)
  {
   return RET_CODE_ERR;
  }
  else
  {
   string strSection = strLine.substr(1, nPos-1);
   if (strSection.empty())
   {
    return RET_CODE_ERR;
   }
   else
   {
    CIniSection iniSection;
    iniSection.strSection = strSection;
    strSectionName = strSection;    
    m_iniSections.push_back(iniSection);
    return RET_CODE_OK;
   }
  }   
 }
 else if ((nPos=strLine.find('=')) != string::npos) // INI项
 {
  string strLeft = strLine.substr(0, nPos);
  strLeft = Trim(strLeft);   
  if (strLeft.empty())
  {
   return RET_CODE_ERR;
  }
  else
  {
   string strRight = strLine.substr(nPos+1);
   strRight = Trim(strRight);
   if (strRight.empty())
   {
    return RET_CODE_ERR;
   }
   else
   {
    for (vector<CIniSection>::iterator iter = m_iniSections.begin();
     iter != m_iniSections.end();
     ++iter)
    {
     if (iter->strSection == strSectionName)
     {
      iter->vecSection.push_back(make_pair(strLeft, strRight));
      break;
     }
    }
    return RET_CODE_OK;
   }
  }   
 }
 else if (strLine.find_first_not_of(" /t/r/n") != string::npos) // 其他情况
 {
  return RET_CODE_ERR;
 }
 else               // 空行
 {
  return RET_CODE_OK;
 }
}


INLINE
string CIniProfile::Trim(const string &strInput)
{
 string str = strInput;

 string::iterator i = str.begin();
 for (; i != str.end(); i++)
 {
  if (!isspace(*i))
  {
   break;
  }
 }

 if (i == str.end()) // 空串,直接返回
 {
  str.clear();
  return str;
 }
 else
 {
  str.erase(str.begin(), i);
 }

 // str不可能是空串了
 for (i = str.end() - 1; ;i--)
 {
  if (!isspace(*i))
  {
   str.erase(i + 1, str.end());
   break;
  }
  if (i == str.begin())
  {
   str.clear();
   break;
  }
 }

 return str;
}


INLINE
void CIniProfile::ToXMLFormat(const string &strXmlFilePath)
{
 string strOut  = "<?xml version=/"1.0/" encoding=/"ANSI/"?>/n";
 strOut += "<Profile>/n";
 for (vector<CIniSection>::iterator iter = m_iniSections.begin();
  iter != m_iniSections.end();
  ++iter)
 {
  strOut += "/t<" + iter->strSection + ">/n";
  for (vector<INI_ITEM>::iterator iniIter = iter->vecSection.begin();
   iniIter != iter->vecSection.end();
   ++iniIter)
  {   
   strOut += "/t/t<" + iniIter->first;
   strOut += " value=/"" + iniIter->second;
   strOut += "/"/>/n";
  }
  strOut += "/t</" + iter->strSection + ">/n";
 }
 strOut += "</Profile>/n";

 ofstream ofs(strXmlFilePath.c_str(), ofstream::app);
 ofs.write(strOut.c_str(), strOut.length());
}


__LTK_END

 

main.cpp文件

#include <string>
#include <iostream>
#include "IniProfile.h"

using namespace std;


int main(int, char *[])
{
 CIniProfile profile;
 profile.LoadConfig("test.etc");


 string strValue;

 cout<<"the [test] section:/n";

 profile.GetItem("test", "normal_1", strValue);
 cout<<"normal_1 = ";
 cout<<"["<<strValue<<"]"<<endl;

 profile.GetItem("test", "normal_2", strValue);
 cout<<"normal_2 = ";
 cout<<"["<<strValue<<"]"<<endl;

 profile.GetItem("test", "normal_3", strValue);
 cout<<"normal_3 = ";
 cout<<"["<<strValue<<"]"<<endl;

 profile.GetItem("test", "normal_4", strValue);
 cout<<"normal_4 = ";
 cout<<"["<<strValue<<"]"<<endl;


 cout<<"/nthe [others] section:"<<endl;

 profile.GetItem("others", "name", strValue);
 cout<<"name = ";
 cout<<"["<<strValue<<"]"<<endl;

 profile.GetItem("others", "hobbies", strValue);
 cout<<"hobbies = ";
 cout<<"["<<strValue<<"]"<<endl;

 return 0;
};

配置文件

#this is a testing ini file.


[test]
#this is comment for normal_1
normal_1=value_1 

#this is comment for normal_2
normal_2 = value_2
normal_3    =   value_3
normal_4             =  hhh jjjjj

 

PS:插入代码时,没有C++风格的,只有直接粘贴了,有点难看,也没有整理格式了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值