利用sampleini库实现c/c++操作ini配置文件

news2025/1/13 8:10:01

github sampleini库下载链接: https://github.com/brofield/simpleini

 下载后只需一下三个文件即可:

配置文件格式:采用以下格式;

 

 1. 加载配置文件前重要设置

/*设置是否使用utf8编码作为加载/保存; 在ini数据被加载后不可设置; 默认true;*/
void SetUnicode(bool a_bIsUtf8 = true) {
    if (!m_pData) m_bStoreIsUtf8 = a_bIsUtf8;
};

/*是否允许使用多个相同的key;
  若为true; 则:
  [section]
  test = value1;
  test = value2;
  上面两个key相同,value不同可被允许设置;

  若为false;
  [section]
  test = value2; //value1 为上次值,被覆盖;
*/
void SetMultiKey(bool a_bAllowMultiKey = true) {
    m_bAllowMultiKey = a_bAllowMultiKey;
}

/*是否允许数据value跨越文件中的多行*/
void SetMultiLine(bool a_bAllowMultiLine = true) {
    m_bAllowMultiLine = a_bAllowMultiLine;
}

/*写入键/值时是否应该在等号周围添加空格;
  若为true; 则 key = value 等号两边有空格;
  若为false;则 key=value 等号两边无空格;
*/
void SetSpaces(bool a_bSpaces = true) {
    m_bSpaces = a_bSpaces;
}

/*是否应该识别或解析单行value中的引号;*/
void SetQuotes(bool a_bParseQuotes = true) {
    m_bParseQuotes = a_bParseQuotes;
}

//默认状态如下;
printf("IsUnicode = %d \n",conf.IsUnicode());//0
printf("IsMultiKey = %d \n",conf.IsMultiKey());//0
printf("IsMultiLine = %d \n",conf.IsMultiLine());//0
printf("UsingSpaces = %d \n",conf.UsingSpaces());//1
printf("UsingQuotes = %d \n",conf.UsingQuotes());//0

2. 加载数据

//参数为文件路径
SI_Error LoadFile(
    const char * a_pszFile
    );

(1) 该函数有很多同名函数(重载函数);

(2) 该函数加载是将配置文件从磁盘上加载到内存中; 接下来的很多操作如:setValue等仅仅是改变内存中的数据;在系统掉电是不会保存到磁盘上的; 在内存中操作的目的就是快;

(3) 要想将内存中改变的数据保存到磁盘,需要调用 saveFile()函数将内存中的数据保存到磁盘上;

3. 获取配置信息

/*获取所有[section]名字;
  返回的名字存储在a_names中;
  有定义: typedef std::list<Entry> TNamesDepend; 可知实际为list;
*/
void GetAllSections(
    TNamesDepend & a_names
    ) const;

/*检索所有[section]中的key和val键值对;*/
const TKeyVal * GetSection(
    const SI_CHAR * a_pSection
    ) const;

/*获取[section]中的所有key值,保存到 a_names中; */
bool GetAllKeys(
    const SI_CHAR * a_pSection,
    TNamesDepend &  a_names
    ) const;

/*根据section,key获取对应的value*/
 const SI_CHAR * GetValue(
    const SI_CHAR * a_pSection,
    const SI_CHAR * a_pKey,
    const SI_CHAR * a_pDefault     = NULL,
    bool *          a_pHasMultiple = NULL
    ) const;

 //根据section,key获取bool类型,double类型,long类型,
 bool GetBoolValue(
    const SI_CHAR * a_pSection,
    const SI_CHAR * a_pKey,
    bool            a_bDefault     = false,
    bool *          a_pHasMultiple = NULL
    ) const;
 double GetDoubleValue(
    const SI_CHAR * a_pSection,
    const SI_CHAR * a_pKey,
    double          a_nDefault     = 0,
    bool *          a_pHasMultiple = NULL
    ) const;
  bool GetBoolValue(
    const SI_CHAR * a_pSection,
    const SI_CHAR * a_pKey,
    bool            a_bDefault     = false,
    bool *          a_pHasMultiple = NULL
    ) const;

4. 修改(内存)内容

/*设置值
  参数1: section字符串
  参数2: key字符串
  参数3: value字符串
*/
SI_Error SetValue(
const SI_CHAR * a_pSection,
const SI_CHAR * a_pKey,
const SI_CHAR * a_pValue,
const SI_CHAR * a_pComment      = NULL,
bool            a_bForceReplace = false
)

SI_Error SetLongValue(
const SI_CHAR * a_pSection,
const SI_CHAR * a_pKey,
long            a_nValue,
const SI_CHAR * a_pComment      = NULL,
bool            a_bUseHex       = false,
bool            a_bForceReplace = false
);

SI_Error SetDoubleValue(
const SI_CHAR * a_pSection,
const SI_CHAR * a_pKey,
double          a_nValue,
const SI_CHAR * a_pComment      = NULL,
bool            a_bForceReplace = false
);

SI_Error SetBoolValue(
const SI_CHAR * a_pSection,
const SI_CHAR * a_pKey,
bool            a_bValue,
const SI_CHAR * a_pComment      = NULL,
bool            a_bForceReplace = false
);

调用了上述设置key对应的值后并不能修改磁盘上的内容;原因是设置的内容是loadFile到内存中的数据;

需要使用 saveFile() 函数才能真正将内存中的数据保存到磁盘上;

//内部调用了继承了OutputWriter类的FileWriter类,并调用了write函数;
FILE *fp = fopen("./config.ini","w+");
conf.SaveFile(fp);
fclose(fp);

或者

//其内部也是将文件用fopen打开,然后调用saveFile(FILE *);
conf.SaveFile("./config.ini");

 5. 删除节点/键/值

//将会删掉[section]为"server"的节点;
conf.Delete("server", NULL);

//仅删掉[section]为type, key为"_int"的键和值;
conf.Delete("type", "_int");

//删除[section]为"type",key为"_long"的键和值;
conf.DeleteValue("type", "_long", NULL);	

//删除[section]为"type",key为"_bool"的键和值(不管值是否能够对应都会被删);
conf.DeleteValue("type", "_bool", "false");

 6. 测试示例

#include <iostream>
#include "SimpleIni.h"
#include <list>

using namespace std;

int main()
{
	SI_Error err;
	
	CSimpleIniA conf;
	
	conf.SetUnicode(true);//设置为utf8编码;

	//从磁盘加载到内存中;
	err = conf.LoadFile("./config.ini");
	if(SI_OK != err){
		cout << "load file err" << endl;
		return -1;
	}
	
	CSimpleIniA::TNamesDepend secNames;
	//获取所有section
	conf.GetAllSections(secNames);

	//遍历list
	for(const auto &iter : secNames){
		cout << "[section] = " << iter.pItem << endl;

		//通过section名字获取键值对;
		const CSimpleIniA::TKeyVal *pkeyVal = conf.GetSection(iter.pItem);
		if(nullptr != pkeyVal){
			for(const auto &iter : *pkeyVal){
				cout << iter.first.pItem << " = " << iter.second << endl;
			}
		}
	}

	CSimpleIniA::TNamesDepend keyNames;
	if(true == conf.GetAllKeys("message", keyNames)){ //发现对应的section名,返回true
		printf("\n");
		for(const auto &iter : keyNames){
			cout << "keyName = " << iter.pItem << endl;
		}
	}

	CSimpleIniA::TNamesDepend valNames;
	if(true == conf.GetAllValues("server", "ip", valNames)){
		printf("\n");
		for(const auto &iter : valNames){
			cout << "valName = " << iter.pItem << endl;
		}
	}

	const char *val =  conf.GetValue("server", "port");
	if(val)
		cout << "val = " << val << endl;


	printf("bool = %d \n",conf.GetBoolValue("type", "_bool"));
	printf("_int = %ld \n",conf.GetLongValue("type", "_int"));
	printf("_double = %lf \n",conf.GetDoubleValue("type", "_double"));
	printf("_long = %ld \n",conf.GetLongValue("type", "_long"));

	err = conf.SetValue("type", "_bool", "false");
	if(err == SI_UPDATED){

		printf("update bool ok \n");
	}
	
	conf.SetLongValue("type", "_int", 666);
	conf.SetDoubleValue("type", "_double", 20.222);

	conf.Delete("server", NULL);//将会删掉[section]为"server"的节点;
	conf.Delete("type", "_int");//删掉[section]为type, key为"_int"的键和值;

	conf.DeleteValue("type", "_long", NULL);	//删除[section]为"type",key为"_long"的键和值;
	conf.DeleteValue("type", "_bool", "false");//删除[section]为"type",key为"_bool"的键和值(不管值是否能够对应都会被删);

	//才能完成真正的写;
	#if 0 //ok
	
	FILE *fp = fopen("./config.ini","w+");
	conf.SaveFile(fp);
	fclose(fp);
	#else
	conf.SaveFile("./config.ini");//其内部也是将文件用fopen打开,然后调用saveFile(FILE *);
	#endif 
	
	return 0;
}

实现了ini配置文件的增删改查; 而且可动态增加配置; 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/471386.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】18.哈希

1.unordered_set和unordered_map 使用与set和map的用法一样 #include <iostream> #include <unordered_map> #include <unordered_set> #include <map> #include <set> #include <string> #include <vector> #include <time.h&…

QImage 如何设置图片的透明度

最近遇到了一些这样的需求&#xff0c;在窗口可以调节显示图片的透明度&#xff0c;但是不能影响其他图片。一个窗口显示的图片并不是一张&#xff0c;而是多张通过绘制的形式叠加起来的。可以理解为类似图层。 就像下面这个组合一样&#xff0c;想法是在拖动右侧透明度的滑条…

ACM MM23 Workshop|多媒体+无人机

摘要&#xff1a; 无人驾驶飞行器 (UAV)&#xff0c;也称为无人机&#xff0c;由于能够从空中捕获高质量的多媒体数据&#xff0c;近年来变得越来越流行。 随着航空摄影、电影摄影和测绘等多媒体应用的兴起&#xff0c;无人机已成为收集丰富多样的多媒体内容的强大工具。 本次…

elasticsearch结构化查询

在上一篇中我们介绍了DSL相关的知识&#xff0c;接下来我们将会学习elasticsearch的结构化查询&#xff0c;同时也实践一下上一篇的DSL的查询用法 什么是结构化搜索? 从《Elasticsearch权威指南》上摘取部分解释如下: 结构化搜索是指查询包含内部结构的数据。日期&#xff0…

当我们在谈论ChatGPT时,我们在谈论什么?

当我们在谈论ChatGPT时&#xff0c;我们在谈论什么&#xff1f; 文章目录 当我们在谈论ChatGPT时&#xff0c;我们在谈论什么&#xff1f;一、介绍GPT-4相比GPT-3.5有何不同呢1.交谈能力2.多语言翻译精确度3.视觉输入 二、应用领域1.小镇做题家 (学术研究)2.Cosplay&#xff0c…

优思学院|质量大师的那些名言(三)【质量是一种习惯】

格言是一种简洁明了、简练有力的表达方式&#xff0c;通常蕴含着深刻的哲理和智慧&#xff0c;能够为我们提供指导和启示。 在《质量大师的那些名言》系列中&#xff0c;优思学院将透过这些名言&#xff0c;用最简单、直接、深刻的方式教授质量和六西格玛管理。 概述 在现代商…

ChatGPT 目前到底能帮助我们程序员做什么?

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&#x1…

异常中断处理

异常或中断是用户程序中最基本的一种执行流程或形态。这部分主要对ARM架构下的异常中断做详细说明。 ARM一共有7种类型的异常&#xff0c;按优先级从高到低的排列如下&#xff1a; 复位异常&#xff08;Reset&#xff09;、数据异常&#xff08;Data Abort&#xff09;、快速…

工业和信息化部发布《关于电信设备进网许可制度若干改革举措的通告》

按照《国务院办公厅关于深化电子电器行业管理制度改革的意见》&#xff08;国办发〔2022〕31号&#xff09;要求&#xff0c;工业和信息化部发布《关于电信设备进网许可制度若干改革举措的通告》&#xff08;工信部信管函〔2023〕14号&#xff09;&#xff0c;集中公布动态调整…

2023,你了解Kafka吗?深入详解

- 消息队列的核心价值 - 解耦合。 异步处理 例如电商平台&#xff0c;秒杀活动。一般流程会分为&#xff1a;1: 风险控制、2&#xff1a;库存锁定、3&#xff1a;生成订单、4&#xff1a;短信通知、5&#xff1a;更新数据。 通过消息系统将秒杀活动业务拆分开&#x…

**MySQL关联查询七种方式详解与应用实例**,你的掌握了吗

当我们需要从多个表中查询数据时&#xff0c;就需要使用关联查询了。MySQL支持七种不同类型的关联查询&#xff1a;内连接、左连接、右连接、全外连接、交叉连接、自连接和自然连接。本文将讲解这七种关联查询的SQL语句、示例以及应用场景。 一、 前言 关联查询是数据库操作中…

Leetcode 37 解数独

Leetcode解数独 题目描述题解1(按Board行列回溯&#xff1a;较直接) 题目描述 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次数字 1-9 在每一列只能出现一次数字 1-9 在每一个以粗实线分隔的…

postgresql|数据库|批量执行SQL脚本文件的shell脚本

前言&#xff1a; 对于数据库的维护而言&#xff0c;肯定是有SQL脚本的执行&#xff0c;例如&#xff0c;某个项目需要更新&#xff0c;那么&#xff0c;可能会有很多的SQL脚本需要执行&#xff0c;SQL脚本可能会包含有建表&#xff0c;插入数据&#xff0c;索引建立&#xff…

Vue项目的性能优化

前言 Vue 框架通过数据双向绑定和虚拟 DOM 技术&#xff0c;帮我们处理了前端开发中最脏最累的 DOM 操作部分&#xff0c; 我们不再需要去考虑如何操作 DOM 以及如何最高效地操作 DOM&#xff1b;但 Vue 项目中仍然存在项目首屏优化、Webpack 编译配置优化等问题&#xff0c;所…

Towards Principled Disentanglement for Domain Generalization

本文用大量的理论论述了基于解纠缠约束优化的域泛化问题。 这篇文章认为以往的文章在解决域泛化问题时所用的方法都是non-trivial的&#xff0c;也就是说没有作严格的证明&#xff0c;是不可解释的&#xff0c;而本文用到大量的定理和推论证明了方法的有效性。 动机 因为域泛…

客户管理系统的作用有哪些?

阅读本文您将了解&#xff1a;1.客户管理系统的作用&#xff1b;2.客户管理系统软件怎么用&#xff1b;3.客户管理的注意事项。 一、客户管理系统的作用 客户是企业的重要财富&#xff0c;因此客户管理是企业发展过程中至关重要的一部分&#xff0c;那么客户管理怎么做&#…

把字符串转换成整数

题目&#xff1a;把字符串转换成整数 思路&#xff1a; 如果对于一般规则的数字“字符串”转化为数字都很容易&#xff0c;比如&#xff1a; 对于“123456”可以利用如下代码进行转化&#xff1a; string str"123456"; int ans 0; for (int i0; i<str.size(); …

Elesticesearch

1. 概述 应用场景&#xff1a; 给你一个巨大的文档数据&#xff0c;文档中存储着许多非结构化的数据&#xff0c;如下&#xff1a; {“id” : “1”, “name” : “佛山张学友”, “age” : “15”}, {“name” : “广州周润发”, “height” : “182”}, …中间有10000万行……

ABAP 二分法查找与SORT排序

需求场景 需要对内表排序&#xff0c;按降序排列&#xff0c;获取第一行&#xff1b;二分法查找需要的数据 我按照降序排列后&#xff0c;获取到了第一行&#xff0c;但是通过二分法查找没有获取到 二分法查找 二分查找&#xff0c;对排序数组通过二分区间排除的方法进行快速…

最好用的六款虚拟机软件,赶紧收藏

在日常工作和学习中,我们常常需要在一台电脑上运行多个操作系统,以便进行软件测试、开发、学习以及实验等任务。虚拟机软件就是一种崭新的技术,它可以在一台电脑上运行多个操作系统,为用户提供了更高效、安全、稳定和智能化的工作和学习环境。今天我为大家介绍6款优秀的虚拟…