简单封装的一个ini解析处理类(支持跨平台)。支持功能:

  1. 加载并解析指定ini文件中的配置;
  2. 读取指定 section 下的指定 key 的值。提示:支持按数值型读取,或按文本类型读取;
    使用示例:
     auto fWidth         = 480.0f;
    auto fHeight = 320.0f; ns_ini::IniParser ini;
    ini.open(strConfigFile.c_str());
    fWidth = ini.readFloat("glview", "screen_width", fWidth);
    fHeight = ini.readFloat("glview", "screen_height", fHeight);
  3. 支持新段、项、值写入;提示:如果写入的项是已经存在的,则为修改旧项值;
    示例:
     auto fWidth         = 480.0f;
    auto fHeight = 320.0f; ns_ini::IniParser ini;
    ini.open(strConfigFile.c_str());
    fWidth = ini.readFloat("glview", "screen_width", fWidth);
    fHeight = ini.readFloat("glview", "screen_height", fHeight); ini.writeFloat("glview", "screen_height, 777.77f); // 将旧值修改为 777.77f
    ini.writeInt("glview", "screen_height, 666); // 再次将旧值修改为 666
    ini.writeText("glview", "screen_height, "jacc.kim"); // 再次将旧值修改为 文本"jacc.kim"

源码如下:

 /******************************************************************************

                              I'm jacc.kim

     CreateDate: 2017-06-13 17:12:16
FileName : JKIniParser.h
Version : 1.00
Author : jacc.kim
Summary : ini parser wrapper ******************************************************************************/
#pragma once #include <list>
#include <map> namespace ns_ini
{ class Section; /******************************************************************************
* create : (jacc.kim) [06-13-2017]
* summary : class IniParser
******************************************************************************/
class IniParser
{
public:
void setIniFile(const char* const pcszIniFile);
bool open(const char* const pcszIniFile = nullptr);
bool save(const char* const pcszIniFile = nullptr);
void close(); unsigned int getSectionAmount() const;
bool isSectionExisted(const char* const pcszSection) const;
bool isParameterExisted(const char* const pcszSection, const char* const pcszParameter) const; int readInt(const char* const pcszSection, const char* const pcszKey, const int def = ) const;
unsigned int readUnsignedInt(const char* const pcszSection, const char* const pcszKey, const unsigned int def = 0u) const;
bool readBool(const char* const pcszSection, const char* const pcszKey, const bool def = false) const;
float readFloat(const char* const pcszSection, const char* const pcszKey, const float def = 0.0f) const;
double readDouble(const char* const pcszSection, const char* const pcszKey, const double def = 0.0) const;
const char* readText(const char* const pcszSection, const char* const pcszKey, const char* const def = nullptr) const; // !!!note: write existed section & key, the old value will be replaced.
void writeInt(const char* const pcszSection, const char* const pcszKey, const int value);
void writeUnsignedInt(const char* const pcszSection, const char* const pcszKey, const unsigned int value);
void writeBool(const char* const pcszSection, const char* const pcszKey, const bool value);
void writeFloat(const char* const pcszSection, const char* const pcszKey, const float value);
void writeDouble(const char* const pcszSection, const char* const pcszKey, const double value);
void writeText(const char* const pcszSection, const char* const pcszKey, const char* const value); bool remove(const char* const pcszSection, const char* const pcszKey);
bool remove(const char* const pcszSection);
void clear(); public:
IniParser();
~IniParser(); Section* getSection(const char* const pcszSection) const;
Section& operator[](const char* const pcszSection) const; private:
IniParser(const IniParser& rhs)/* = delete*/;
IniParser& operator=(const IniParser& rhs)/* = delete*/; void trimLeft(char*& p, char*& q);
void trimRight(char*& p, char*& q);
void trim(char*& p, char*& q);
void trimRN0(char*& p, char*& q);
bool isEndWithN(const char* p, const size_t nLength);
bool stringEqual(const char* p, const char* q, int nChar = INT_MAX) const;
bool isSectionName(char* p, char* q);
char* splitKeyValue(char* p, char* q);
void parseIniLine(char* szIniLine);
void addSection(char* szSectionName);
void addParameter(char* szKey, char* szValue); private:
typedef std::list<Section*> SectionList;
typedef SectionList::iterator SectionListIter; // key = section name, value = section's ptr
typedef std::map <std::string, SectionListIter> SectionMap; private:
std::string m_strIniFile; // ini file name
SectionList m_listSections; // all sections.
SectionMap m_mapSectionName; // section <--> index mapping.(only reference.) };//class IniParser }//namespace ns_ini

IniParser.h 文件

 #include "JKIniParser.h"

 namespace ns_ini
{ /******************************************************************************
* create : (jacc.kim) [06-13-2017]
* summary : class Section
******************************************************************************/
class Section
{
public:
struct Parameter
{
std::string key;
std::string value;
};//struct Parameter typedef std::list<Parameter> ParameterList;
typedef ParameterList::iterator ParameterListIter;
typedef std::map<std::string, ParameterListIter> ParameterMap; public:
Section(const char* pcszSectionName) : m_strSectionName (pcszSectionName)
, m_listParameters ()
, m_mapParameterKeys()
{} ~Section() {
this->clear();
} const char* getSectionName() const {
return m_strSectionName.c_str();
} bool isParameterExisted(const char* const pcszKey) const {
return m_mapParameterKeys.find(pcszKey) != m_mapParameterKeys.end();
} Parameter& operator[](const char* const pcszKey) const {
auto iter = m_mapParameterKeys.find(pcszKey);
return *(iter->second);
} const char* read(const char* const pcszKey) {
const char* pcszRetValue = nullptr;
if (nullptr != pcszKey) {
auto iter = m_mapParameterKeys.find(pcszKey);;
if (m_mapParameterKeys.end() != iter) {
pcszRetValue = (*(iter->second)).value.c_str();
}
}
return pcszRetValue;
} bool write(const char* const pcszKey, const char* const pcszValue) {
auto iter = m_mapParameterKeys.find(pcszKey);
if (m_mapParameterKeys.end() == iter) {
Parameter param = { pcszKey, pcszValue };
m_listParameters.emplace_back(param);
m_mapParameterKeys[pcszKey] = --m_listParameters.end();
return true;
}
(*this)[pcszKey].value = pcszValue;
return true;
} bool remove(const char* pcszKey) {
auto bIsSuccess = false;
if (nullptr != pcszKey) {
auto iter = m_mapParameterKeys.find(pcszKey);
if (m_mapParameterKeys.end() != iter) {
m_listParameters.erase(iter->second);
m_mapParameterKeys.erase(iter);
bIsSuccess = true;
}
}
return bIsSuccess;
} void clear() {
m_listParameters.clear();
m_mapParameterKeys.clear();
} ParameterList& getAllParameters() {
return m_listParameters;
} private:
std::string m_strSectionName;
ParameterList m_listParameters;
ParameterMap m_mapParameterKeys; };//class Section ///////////////////////////////////////////////////////////////////////////////
// class IniParser
IniParser::IniParser() : m_strIniFile ("")
, m_listSections ()
, m_mapSectionName()
{ } IniParser::~IniParser() {
this->clear();
} void IniParser::setIniFile(const char* const pcszIniFile) {
if (nullptr == pcszIniFile) {
return;
}
m_strIniFile = pcszIniFile;
} bool IniParser::open(const char* const pcszIniFile/* = nullptr*/) {
auto bIsSuccess = false;
const char* pcszOpenFile = nullptr != pcszIniFile ? pcszIniFile : m_strIniFile.c_str();
if (nullptr == pcszOpenFile) {
return bIsSuccess;
}
if (nullptr != pcszIniFile) {
this->setIniFile(pcszIniFile);
}
this->clear();
auto pINIFile = fopen(pcszIniFile, "rb");
if (nullptr != pINIFile) {
bIsSuccess = true;
const size_t nBUFF_SIZE = ;
char szBuff[nBUFF_SIZE];
while (!feof(pINIFile)) {
memset((void*)szBuff, 0x0L, nBUFF_SIZE);
fgets(szBuff, nBUFF_SIZE, pINIFile);
this->parseIniLine(szBuff);
}
fclose(pINIFile);
pINIFile = nullptr;
} return bIsSuccess;
} bool IniParser::save(const char* const pcszIniFile/* = nullptr*/) {
auto bIsSuccess = false;
const char* pcszSaveFile = nullptr != pcszIniFile ? pcszIniFile : m_strIniFile.c_str();
if (nullptr == pcszSaveFile) {
return bIsSuccess; // 没有可保存的路径
}
::remove(pcszSaveFile);
auto pINIFile = fopen(pcszSaveFile, "ab+");
if (nullptr != pINIFile) {
bIsSuccess = true;
auto iter = m_listSections.begin();
const auto iterend = m_listSections.end();
const size_t nBUFF_SIZE = ;
char szBuffer[nBUFF_SIZE];
Section* pSection = nullptr;
for (; iterend != iter;/* ++iter*/) {
pSection = *iter;
const char* pcszSectionName = pSection->getSectionName();
fputs("[", pINIFile);
fputs(pcszSectionName, pINIFile);
fputs("]\r\n", pINIFile);
auto& allParameters = (*iter)->getAllParameters();
auto listiter = allParameters.begin();
const auto listiterend = allParameters.end();
for (; listiterend != listiter; ++listiter) {
auto& param = *listiter;
memset((void*)szBuffer, 0x0L, nBUFF_SIZE);
memcpy(szBuffer, param.key.c_str(), param.key.length());
szBuffer[param.key.length()] = '=';
memcpy(szBuffer + param.key.length() + , param.value.c_str(), param.value.length());
const auto nEndPos = param.key.length() + + param.value.length();
szBuffer[nEndPos + ] = '\0';
fputs(szBuffer, pINIFile);
if (!this->isEndWithN(szBuffer, nEndPos + )) {
fputs("\r\n", pINIFile);
}
}
if (iterend != ++iter) {
fputs("\r\n", pINIFile);
}
}
fclose(pINIFile);
pINIFile = nullptr;
} return bIsSuccess;
} void IniParser::close() {
this->save();
this->clear();
this->setIniFile(nullptr);
} unsigned int IniParser::getSectionAmount() const {
return static_cast<unsigned int>(m_listSections.size());
} bool IniParser::isSectionExisted(const char* const pcszSection) const {
return nullptr != this->getSection(pcszSection);
} bool IniParser::isParameterExisted(const char* const pcszSection, const char* const pcszParameter) const {
auto pSection = this->getSection(pcszSection);
return nullptr != pSection && pSection->isParameterExisted(pcszParameter);
} int IniParser::readInt(const char* const pcszSection, const char* const pcszKey, const int def/* = 0*/) const {
int retValue = def;
const char* pcszText = this->readText(pcszSection, pcszKey, nullptr);
if (nullptr != pcszText) {
if ( != sscanf(pcszText, "%d", &retValue)) {
retValue = def; // 读取失败.
}
}
return retValue;
} unsigned int IniParser::readUnsignedInt(const char* const pcszSection, const char* const pcszKey, const unsigned int def/* = 0u*/) const {
unsigned int retValue = def;
const char* pcszText = this->readText(pcszSection, pcszKey, nullptr);
if (nullptr != pcszText) {
if ( != sscanf(pcszText, "%u", &retValue)) {
retValue = def; // 读取失败.
}
}
return retValue;
} bool IniParser::readBool(const char* const pcszSection, const char* const pcszKey, const bool def/* = false*/) const {
bool retValue = def;
const char* pcszText = this->readText(pcszSection, pcszKey, nullptr);
if (nullptr != pcszText) {
int iTempVal = ;
if ( == sscanf(pcszText, "%d", &iTempVal)) {
return == iTempVal ? false : true;
} else if (this->stringEqual(pcszText, "true")) {
return true;
} else {
return false;
}
}
return retValue;
} float IniParser::readFloat(const char* const pcszSection, const char* const pcszKey, const float def/* = 0.0f*/) const {
float retValue = def;
const char* pcszText = this->readText(pcszSection, pcszKey, nullptr);
if (nullptr != pcszText) {
if ( != sscanf(pcszText, "%f", &retValue)) {
retValue = def; // 读取失败.
}
}
return retValue;
} double IniParser::readDouble(const char* const pcszSection, const char* const pcszKey, const double def/* = 0.0*/) const {
double retValue = def;
const char* pcszText = this->readText(pcszSection, pcszKey, nullptr);
if (nullptr != pcszText) {
if ( != sscanf(pcszText, "%lf", &retValue)) {
retValue = def; // 读取失败.
}
}
return retValue;
} const char* IniParser::readText(const char* const pcszSection, const char* const pcszKey, const char* const def/* = nullptr*/) const {
const char* pcszRetValue = def;
auto pSection = this->getSection(pcszSection);
if (nullptr != pSection) {
pcszRetValue = pSection->read(pcszKey);
}
return pcszRetValue;
} void IniParser::writeInt(const char* const pcszSection, const char* const pcszKey, const int value) {
const size_t nBUFF_SIZE = ;
char szBuff[nBUFF_SIZE];
memset((void*)szBuff, 0x0L, nBUFF_SIZE);
sprintf(szBuff, "%d", value);
this->writeText(pcszSection, pcszKey, szBuff);
} void IniParser::writeUnsignedInt(const char* const pcszSection, const char* const pcszKey, const unsigned int value) {
const size_t nBUFF_SIZE = ;
char szBuff[nBUFF_SIZE];
memset((void*)szBuff, 0x0L, nBUFF_SIZE);
sprintf(szBuff, "%u", value);
this->writeText(pcszSection, pcszKey, szBuff);
} void IniParser::writeBool(const char* const pcszSection, const char* const pcszKey, const bool value) {
const size_t nBUFF_SIZE = ;
char szBuff[nBUFF_SIZE];
memset((void*)szBuff, 0x0L, nBUFF_SIZE);
sprintf(szBuff, "%d", value ? : );
this->writeText(pcszSection, pcszKey, szBuff);
} void IniParser::writeFloat(const char* const pcszSection, const char* const pcszKey, const float value) {
const size_t nBUFF_SIZE = ;
char szBuff[nBUFF_SIZE];
memset((void*)szBuff, 0x0L, nBUFF_SIZE);
sprintf(szBuff, "%g", value);
this->writeText(pcszSection, pcszKey, szBuff);
} void IniParser::writeDouble(const char* const pcszSection, const char* const pcszKey, const double value) {
const size_t nBUFF_SIZE = ;
char szBuff[nBUFF_SIZE];
memset((void*)szBuff, 0x0L, nBUFF_SIZE);
sprintf(szBuff, "%g", value);
this->writeText(pcszSection, pcszKey, szBuff);
} void IniParser::writeText(const char* const pcszSection, const char* const pcszKey, const char* const value) {
if (nullptr != pcszSection && nullptr != pcszKey && nullptr != value) {
auto iter = m_mapSectionName.find(pcszSection);
Section* pSection = nullptr;
if (m_mapSectionName.end() == iter) {
pSection = new (std::nothrow) Section(pcszSection);
if (nullptr == pSection) {
return;
}
m_listSections.emplace_back(pSection);
m_mapSectionName[pcszSection] = --m_listSections.end();
} else {
pSection = *(iter->second);
}
pSection->write(pcszKey, value);
}
} bool IniParser::remove(const char* const pcszSection, const char* const pcszKey) {
auto bIsSuccess = false;
if (nullptr != pcszSection) {
auto iter = m_mapSectionName.find(pcszSection);
if (m_mapSectionName.end() != iter) {
auto pSection = *(iter->second);
if (nullptr != pSection) {
bIsSuccess = pSection->remove(pcszKey);
}
}
}
return bIsSuccess;
} bool IniParser::remove(const char* const pcszSection) {
auto bIsSuccess = false;
if (nullptr != pcszSection) {
auto iter = m_mapSectionName.find(pcszSection);
if (m_mapSectionName.end() != iter) {
auto list_iter = iter->second;
Section* pSection = *list_iter;
if (nullptr != pSection) {
delete pSection;
pSection = nullptr;
}
m_listSections.erase(list_iter);
m_mapSectionName.erase(iter);
bIsSuccess = true;
}
}
return bIsSuccess;
} void IniParser::clear() {
auto iter = m_listSections.begin();
const auto iterend = m_listSections.end();
Section* pSection = nullptr;
for (; iterend != iter; ++iter) {
pSection = *iter;
if (nullptr != pSection) {
delete pSection;
pSection = nullptr;
}
}
m_listSections.clear();
m_mapSectionName.clear();
} Section* IniParser::getSection(const char* const pcszSection) const {
Section* pRetSection = nullptr;
auto iter = m_mapSectionName.find(pcszSection);
if (m_mapSectionName.end() != iter) {
pRetSection = *(iter->second);
}
return pRetSection;
} Section& IniParser::operator[](const char* const pcszSection) const {
auto iter = m_mapSectionName.find(pcszSection);
return *(*(iter->second));
} void IniParser::trimLeft(char*& p, char*& q) {
if (nullptr != p) {
while (' ' == *p && ++p <= q);
}
} void IniParser::trimRight(char*& p, char*& q) {
if (nullptr != q) {
while (' ' == *q && --q >= p);
}
} void IniParser::trim(char*& p, char*& q) {
this->trimLeft(p, q);
this->trimRight(p, q);
} void IniParser::trimRN0(char*& p, char*& q) {
if (nullptr != q) {
while (('\0' == *q || '\r' == *q || '\n' == *q) && --q >= p);
}
} bool IniParser::isEndWithN(const char* p, const size_t nLength) {
if ( == nLength) {
return false;
}
const char* q = p + nLength;
while ('\0' == *q && --q >= p);
return (q >= p) && ('\n' == *q);
} bool IniParser::stringEqual(const char* p, const char* q, int nChar/* = INT_MAX*/) const {
int n = ;
if (p == q) {
return true;
}
while (*p && *q && *p == *q && n < nChar) {
++p;
++q;
++n;
}
if ((n == nChar) || (*p == && *q == )) {
return true;
}
return false;
} bool IniParser::isSectionName(char* p, char* q) {
if (nullptr == p || nullptr == q) {
return false;
}
return '[' == *p && ']' == *q;
} char* IniParser::splitKeyValue(char* p, char* q) {
char* pRetEqualSignPos = p;
while ('=' != *pRetEqualSignPos && ++pRetEqualSignPos < q);
return pRetEqualSignPos;
} void IniParser::parseIniLine(char* szIniLine) {
char* p = szIniLine;
char* q = p + strlen(p);
this->trimRN0(p, q);
this->trim(p, q);
if (p < q) {
// 只有这种情况才需要处理.因为 p > q,肯定不需要处理,说明全都是空格.如果p = q也不需要处理,因为只有一个字符还需要处理什么?
*(q + ) = '\0';
if (this->isSectionName(p, q)) {
*q = '\0';
++p;
this->addSection(p);
} else {
char* szEqualSignPos = this->splitKeyValue(p, q);
if (szEqualSignPos > p && szEqualSignPos < q) {
*szEqualSignPos = '\0';
++szEqualSignPos;
this->addParameter(p, szEqualSignPos);
}
}
}
} void IniParser::addSection(char* szSectionName) {
auto iter = m_mapSectionName.find(szSectionName);
if (m_mapSectionName.end() != iter) {
// 已存在
auto listiter = iter->second;
m_listSections.emplace_back(*listiter);
m_listSections.erase(listiter);
m_mapSectionName.erase(iter);
m_mapSectionName[szSectionName] = --m_listSections.end();
return;
}
Section* pSection = new (std::nothrow) Section(szSectionName);
if (nullptr == pSection) {
return;
}
m_listSections.emplace_back(pSection);
m_mapSectionName[szSectionName] = --m_listSections.end();
} void IniParser::addParameter(char* szKey, char* szValue) {
if (m_listSections.empty()) {
return;
}
auto pSection = m_listSections.back();
pSection->write(szKey, szValue);
} }//namespace ns_ini

IniParser.cpp 文件

如果对该封装有改进或不当之处,欢迎指定、交流!

简单的INI解析封装的更多相关文章

  1. 简单的URL解析

    简单的URL解析,直接举例说明了 function getUrl(){ //如果存在则取到来后面的参数,注意,?不需要取出,substring从1开始,否则取""; var qs ...

  2. 自己动手实现一个简单的JSON解析器

    1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着诸多优点.比如易读性更好,占用空间更少等.在 ...

  3. 非常简单的XML解析(SAX解析、pull解析)

    这里只是把解析的数据当日志打出来了 非常简单的xml解析方式 package com.example.demo.service; import java.io.IOException; import ...

  4. INI解析模块的C++实现

    INI文件格式是某些平台或软件上的配置文件的非正式标准,以节(section)和键(key)构成,常用于微软Windows操作系统中. 节(section) 节用方括号括起来,单独占一行,例如: [s ...

  5. FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  6. FFmpeg的HEVC解码器源代码简单分析:解析器(Parser)部分

    ===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...

  7. FFmpeg的H.264解码器源代码简单分析:解析器(Parser)部分

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  8. 一个简单的json解析器

    实现一个简单地json解析器. 两部分组成,词法分析.语法分析 词法分析 package com.mahuan.json; import java.util.LinkedList; import ja ...

  9. VS Extension+NVelocity系列(一)——构建一个简单的NVelocity解析环境

    一.前言 本节我们将实际实现一个简单的NVelocity解析环境,以便为以后的实例做一些基本工作,虽然NVelocity如何使用已经属于老掉牙的话题,但我只能专门挑出来一章来做铺垫.人生就是这样无奈啊 ...

随机推荐

  1. Java 中的方法内部类

    方法内部类就是内部类定义在外部类的方法中,方法内部类只在该方法的内部可见,即只在该方法内可以使用. 一定要注意哦:由于方法内部类不能在外部类的方法以外的地方使用,因此方法内部类不能使用访问控制符和 s ...

  2. c语言中的size_t

    size_t unsigned int 类型,无符号,它的取值没有负数.用来表示 参数/数组元素个数,sizeof 返回值,或 str相关函数返回的 size 或 长度.sizeof 操作符的结果类型 ...

  3. Python3 面向对象编程高级语法

    1.静态方法: #!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:CarsonLi class Dog(object): def __init ...

  4. Linux线程基础函数

    1. 线程标识: (1) 比较两个线程ID: #include <pthread.h> int pthread_equal(pthread_t tid1, pthread_t tid2); ...

  5. 64_g5

    golang-github-kr-text-devel-0-0.11.git6807e77.f..> 11-Feb-2017 07:48 14250 golang-github-kr-text- ...

  6. 【数位dp入门】【HDU4734】F(x)

    记录减的状态,表示还要凑多少才能达到当前值. 然后进行枚举即可.注意状态数不能重复. #include<bits/stdc++.h> #define N 10010 using names ...

  7. git - 开发者电脑与服务器的配置

    首先公司要有一台git服务器,现在一般都托管在github服务器上,在中国可能会托管到oschina上,oschina有一点好处就是可以免费托管私有项目,而在github上想要托管自己的项目是收费的, ...

  8. Centos7 IP地址配置方法

    1.编辑 ifcfg-eth0 文件 # vim /etc/sysconfig/network-scripts/ifcfg-eth0 2.修改如下内容 BOOTPROTO=”static” #dhcp ...

  9. JavaScript原型与继承(1)

    内容: 创建对象的几种模式以及创建的过程 原型链prototype的理解,以及prototype与 __proto__([[Prototype]])的关系 继承的几种实现 1.常见模式与原型链的理解 ...

  10. R语言平均值和加权平均值

    > a=c(,,) > mean(a) #平均值 [] > wt=c(,,) > weighted.mean(a,wt) #加权平均值 []