C/C++ 操作ini文件(SinpleIni 跨平台库)

告别XML和JSON:用C++的SimpleIni库为你的配置文件减负(附完整封装类) 本文介绍了如何利用C++的SimpleIni库简化配置文件管理,替代XML和JSON格式。通过对比分析,展示了INI格式在轻量级、跨平台和性能方面的优势,并提供了完整的封装类实现和高级应用技巧,帮助开发者提升配置管理效率。 阅读详情
AI摘要

文章介绍了如何使用SimpleIni库在C++中进行ini文件的读写操作,包括加载、保存、增加、修改、删除键值对,以及处理中文乱码问题。此外,还展示了如何封装SimpleIni以适应项目需求。

最近在学习时,发现自己还不会操作ini文件,想着以前工作时接触到的项目或多或少都要用到ini文件去保存初始化程序的数据;所以赶紧去网上搜索以下C/C++操作ini文件都有些什么库可以玩玩;搜索到有:

1. inih:这是C语言小巧的库,更适合嵌入式开发;

2. iniparser:这是C语言的库,挺方便使用的,开源,两个.h文件和两个.c文件,但只能在Linux中使用;

3. simpleini:这是C++的库,挺方便使用的,跨平台,开源,就两个.h文件和一个.c文件,且支持中文;

所以最后我选择了simpleini这个库去学习使用!


目录

一、介绍

1. ini介绍

2. simpleini介绍

二、下载

三、使用

1. 加载ini文件

2. 简单配置

3. 增

1). 添加一个新的节点(section)

2). 添加一个新的 key和value

4. 改

1). 修改值(value)

5. 删

1). 删除 key 和 value

2). 当最后一个key也被删除掉后,section1也会被删除

3). 删除整个节点(section)和其下的所有键(key) 

6. 查

1). 将下图中的ini文件内容读取打印显示

2). 遍历ini文件的所有内容

3). 遍历所有节点(section)

4). 遍历指定节点的键(key)

5). 获取一个键对应多个值 

6). 获取指定节点(section)里有多少键值

7. 保存

1). 保存到文件 

2). 保存到C++字符串

8. 中文乱码问题

四、封装

configdef.h

iniconfig.h

iniconfig.cpp

测试代码:

五、总结


一、介绍

1. ini介绍

ini文件由 [section] 节点 和 key 键 和 value 值 构成。

例如一个简单的ini文件如下所示:

[message]
name = 张三
age = 25
height = 173.2

; 这是一个注释

[server]
ip = 127.0.0.1
port = 6666

message就是节点,节点下方就是它的键和值;server也是一个节点。

如果需要注释,使用英文分号 ' ; ' 即可。

2. simpleini介绍

一个跨平台库,提供了一个简单的API来读取和写入ini风格的配置文件。它支持ASCII、MBCS和Unicode格式的数据文件。它被明确设计为可移植到任何平台,并已在Windows, WinCE和Linux上进行了测试。使用MIT许可证作为开源和免费发布.

功能概述

  • MIT许可允许在所有软件中免费使用(包括GPL和商业软件)
  • 多平台(Windows 95到Windows 10、Windows CE、Linux、Unix)
  • 加载和保存ini风格的配置文件
  • 在所有平台上,配置文件可以使用任何换行格式
  • 对文件格式的自由接受
  • 没有section的键/值,没有值的键
  • 删除部分、键和值周围的空白
  • 支持多行值(嵌入换行字符的值)
  • 可选支持同名的多个键
  • 可选的不区分大小写的节和键(仅针对ASCII字符)
  • 在文件加载时以相同的顺序保存部分和键
  • 尽可能保留文件、节和键上的注释
  • 同时支持char或wchar_t编程接口
  • 同时支持MBCS(系统区域设置)和UTF-8文件编码
  • 在Linux/Unix上,系统区域设置不需要是UTF-8才能加载UTF-8文件
  • 在节、键、值和注释中支持非ascii字符
  • 通过用户编写的转换器类支持非标准字符类型或文件编码
  • 支持以编程方式添加/修改值
  • 在大多数编译器中应该编译没有警告

二、下载

GitHub链接:GitHub - brofield/simpleini: Cross-platform C++ library providing a simple API to read and write INI-style configuration fileshttps://github.com/brofield/simpleini

gitte链接:

simpleini: SimpleIni 是一个跨平台的 C++ 库,提供一个简单的 API 用于操作 ini 配置文件 (gitee.com)https://gitee.com/mirrors/simpleini

下载后解压

 这三个文件可在 Window 或 Linux 环境去使用!


三、使用

以下介绍的用法,Linux和Window环境均可使用! 

 包含头文件:

#include "SimpleIni.h"

#define FILE_NAME    "./test1.ini" 

test1.ini内容如下:

1. 加载ini文件

// 定义ini文档对象
CSimpleIniA ini;

// 加载ini文件
SI_Error rc;
rc = ini.LoadFile(FILE_NAME);	// 另一种方式:SI_Error LoadFile(FILE * a_fpFile);
if (rc < 0) { 
	printf("加载 %s ini 文件失败!\n", FILE_NAME);
	return -1;
}

rc返回值有以下这些:

using SI_Error = int;

constexpr int SI_OK = 0;        //!< No error
constexpr int SI_UPDATED = 1;   //!< An existing value was updated
constexpr int SI_INSERTED = 2;  //!< A new value was inserted

// note: test for any error with (retval < 0)
constexpr int SI_FAIL = -1;     //!< Generic failure
constexpr int SI_NOMEM = -2;    //!< Out of memory error
constexpr int SI_FILE = -3;     //!< File error (see errno for detail error)

2. 简单配置

// 设置INI数据的存储格式,参数为true时保存为UTF-8格式,否则为本地编码格式
ini.SetUnicode(true);

// 是否允许一个关键字对应多个值,默认为允许;若不允许,则将最后一个值作为此关键字关联的值
ini.SetMultiKey(false);

3. 增

 SetValue

参数一:节点

参数二:键

参数三:值

返回值:SI_Error (也就是int类型)

1). 添加一个新的节点(section)

// 添加一个新的 section
rc = ini.SetValue("section1", nullptr, nullptr);
if (rc < 0) { 
	printf("添加section1失败!\n");
	return -1;
}

 

2). 添加一个新的 key和value

// 添加一个新的 key和value
rc = ini.SetValue("section1", "name", "张三");
if (rc < 0) {
	printf("添加name失败!\n");
	return -1;
}
//const char *name = ini.GetValue("section1", "name", "");
//printf("name = %s\n", name);

ini.SetValue("section1", "age", "24");
ini.SetValue("section1", "sex", "男");

注意:如果name存在,则会将name键(key)对应的值(value)修改为张三;

 还可以使用SetLongValue、SetDoubleValue、SetBoolValue去添加:

ini.SetLongValue("server", "length", 173);
ini.SetDoubleValue("server", "weight", 53.5);
ini.SetBoolValue("server", "vip", true);

4. 改

SetValue

参数一:节点

参数二:键

参数三:值

返回值:SI_Error (也就是int类型)

1). 修改值(value)

// 修改value,如果键(name)不存在则添加该 key和value
rc = ini.SetValue("section1", "name", "李四");
if (rc < 0) { 
	printf("修改name失败!\n");
	return -1;
}
//const char *name = ini.GetValue("section1", "name");
//printf("name = %s\n", name);

注意:如果要修改的值对应的键不存在,则会添加改键和值到section1节点中! 

 貌似无法修改节点(section) 和 键(key),我没有找到相关的api。。。

 还可以使用SetLongValue、SetDoubleValue、SetBoolValue去添加:

ini.SetLongValue("server", "length", 1000);
ini.SetDoubleValue("server", "weight", 66.66);
ini.SetBoolValue("server", "vip", false);

5. 删

Delete

参数一:节点

参数二:键

返回值:bool 

bool done = false; 

1). 删除 key 和 value

// 删除 key
done = ini.Delete("section1", "name");
if (false == done) {
	printf("删除 section1 - name 失败!\n");
	return -1;
}

2). 当最后一个key也被删除掉后,section1也会被删除

// 如果最后一个key也被删除了,那么section也会被一起删除掉
bool deleteSectionIfEmpty = true;
done = ini.Delete("section1", "age", deleteSectionIfEmpty);
if (false == done) {
	printf("删除 section1 - age 失败!\n");
	return -1;
}

此时section1中还由两个key,随意上面的代码执行后只会将age给删除掉,并不会也把section1删掉;

 如果将Delete的第三个参数值true去删除sex,那么section1也会一并删掉!

ini.Delete("section1", "sex", true);

将section1还原到一开始的的样子 ,方便下面第3点操作删除

3). 删除整个节点(section)和其下的所有键(key) 

// 删除整个section和其中的所有键
done = ini.Delete("section1", nullptr);
if (false == done) {
	printf("删除整个section和其中的所有键 失败 !\n");
	return -1;
}

执行如上代码,就会将刚刚还原的section1都给删除掉!

6. 查

GetValue

参数一:节点

参数二:键

参数三:如果没找到,返回参数三指定的默认值

返回值:const char *

1). 将下图中的ini文件内容读取打印显示

int _int = std::stoi(ini.GetValue("section", "_int", "-1"));
printf("_int = %d\n", _int);

long long _long = std::stoll(ini.GetValue("section", "_long", "-1"));
printf("_long = %lld\n", _long);

double _double = std::stod(ini.GetValue("section", "_double", "0.0"));
printf("_double = %lf\n", _double);

float _float = std::stof(ini.GetValue("section", "_float", "0.0"));
printf("_float = %f\n", _float);

bool _bool = ini.GetBoolValue("section", "_bool", false);
printf("_bool = %s\n", _bool ? "true" : "false");

std::string _string = ini.GetValue("section", "_string", "");
printf("_string = %s\n", _string.c_str());

std::string _string2 = ini.GetValue("section", "_string2", "");
printf("_string2 = %s\n", _string2.c_str());

char _char = ini.GetValue("section", "_char", "")[0];
printf("_char = %c\n", _char);

std::string ip = ini.GetValue("server", "ip", "0.0.0.0");
printf("ip = %s\n", ip.c_str());

int port = std::stoi(ini.GetValue("server", "port", "-1"));
printf("port = %d\n", port);

std::string name1 = ini.GetValue("server", "name", "");
printf("name = %s\n", name1.c_str());

还可以使用GetLongValue、GetDoubleValue、GetBoolValue去查:

int lenght = ini.GetLongValue("server", "length", -1);
double weight = ini.GetDoubleValue("server", "weight", -1);
bool vip = ini.GetBoolValue("server", "vip", false);

2). 遍历ini文件的所有内容

 GetAllSections:获取所有节点,参数一引用返回list链表;

GetSection:根据参数字符串,获取节点,返回multimap容器;

CSimpleIniA::TNamesDepend sections;
// get all sections
ini.GetAllSections(sections);	
// 遍历所有 section 的 key 和 value
for (const auto &it : sections) {
	const CSimpleIniA::TKeyVal *pKeyVal = ini.GetSection(it.pItem);
	if (nullptr != pKeyVal) {
		for (const auto& it : *pKeyVal) {
			std::cout << it.first.pItem << " = " << it.second << std::endl;
		}
	}
}

3). 遍历所有节点(section)

CSimpleIniA::TNamesDepend sections1;
// 获取所有section
ini.GetAllSections(sections1);
// 遍历所有 sections
for (const auto &it : sections1) {
	std::cout << it.pItem << std::endl;
}

4). 遍历指定节点的键(key)

GetAllKeys:获取所有键,参数二引用返回list链表; 

CSimpleIniA::TNamesDepend keys;
// get all keys in a section
ini.GetAllKeys("section", keys);	
// 遍历 section 指定的所有 key
for (const auto &it : keys) {
	std::cout << it.pItem << std::endl;
}

5). 获取一个键对应多个值 

首先,ini.SetMultiKey(true);得设置为true,否则只会获取到最后一个值,其他会被删除掉;

在ini文件中的server节点添加多几个name键

 使用以下代码获取:

CSimpleIniA::TNamesDepend values;
// 获取 key 所对应的多个 value;ini.SetMultiKey(true);一定要设置为true,
// 否则就只会获取到最后一个,其他删除
ini.GetAllValues("server", "name", values);
// 遍历一个 key 对应多个 value;
for (const auto &it : values) {
	printf("name = %s\n", it.pItem);	
}

6). 获取指定节点(section)里有多少键值

// 获取section里有多少值
int size = ini.GetSectionSize("section");
printf("section 的 key 个数:%d\n", size);

7. 保存

注意:以上增、删、改,只有执行保存代码后,才会在文件做出相应的修改!

1). 保存到文件 

/* 保存到文件中 */
rc = ini.SaveFile(FILE_NAME);
if (rc < 0) { 
	printf("保存 %s ini文件失败\n", FILE_NAME);
}

2). 保存到C++字符串

std::string strIni = "";
ini.Save(strIni);
printf("%s\n", strIni.c_str());

8. 中文乱码问题

window环境写入或者读取中文有乱码现象,将文件编码改成ANSI编码即可!

可以使用notepad++去修改,如下图:

Linux环境出现中文乱码问题,那就新建一个文件,然后再手动敲上需要的信息即可,例如
touch test1.ini    或     vim test1.ini

记得,千万别从从Window拷贝进Linux中,文件中是不会显示出乱码,但是读取写入时会有乱码!

我遇到的乱码问题,通过上面的方法就可以解决了!


四、封装

可以根据自己项目的具体需求去封装成方便调用的接口去使用!

例如我下面的用法:

configdef.h

这个是定义结构体的头文件,从ini文件中读取的数据都存放在结构体中! 

#ifndef _COMMON_CONFIGDEF_H_
#define _COMMON_CONFIGDEF_H_

#include <string>

typedef struct st_env_config {
    // 对应ini文件

	// section
    int _int;
    long _long;
    double _double;
    float _float;
    bool _bool;
	std::string _string;
	char _char;

	// server
	std::string _ip;
	unsigned short _port;



	// 构造函数
    st_env_config() { }
    st_env_config(int _int, long _long, double _double, float _float, bool _bool, std::string _string, char _char, std::string _ip, unsigned short _port) {
        this->_int = _int;
		this->_long = _long;
		this->_double = _double;
		this->_float = _float;
		this->_bool = _bool;
		this->_string = _string;
		this->_char = _char;

		this->_ip = _ip;
		this->_port = _port;
    }
    
    // 赋值运算符重载
    st_env_config &operator=(const st_env_config &config) {
        if (this != &config) {
			this->_int = config._int;
			this->_long = config._long;
			this->_double = config._double;
			this->_float = config._float;
			this->_bool = config._bool;
			this->_string = config._string;
			this->_char = config._char;

			this->_ip = _ip;
			this->_port = _port;
        }
        
        return *this;
    }
    
}_st_env_config;

#endif	// _COMMON_CONFIGDEF_H_

iniconfig.h

这个是封装simpleini的头文件

#ifndef _COMMON_INICONFIG_H_
#define _COMMON_INICONFIG_H_

#include <string>

#include "configdef.h"

#include "../simpleini/SimpleIni.h"



class Iniconfig {
public:
    Iniconfig();
	Iniconfig(const std::string &path, st_env_config &config);
    ~Iniconfig();
    
	// 加载ini文件
    bool loadfile(const std::string &path);
	// 保存ini文件
	bool saveFile(const std::string &fileName);

	// 设置INI数据的存储格式,参数为true时保存为UTF-8格式,否则为本地编码格式
	void setUnicode(const bool utf8 = true);
	// 是否允许一个关键字对应多个值,默认为允许;若不允许,则将最后一个值作为此关键字关联的值,其他删除
	void setMultiKey(const bool multKey = false);

	// 获取ini文件中的数据,保存到结构体中
	bool getData(st_env_config &config);

	// 获取ini文件字符串
	std::string getIniStr();

	// 添加一个新的section
	bool addSection(const std::string &section);
	// 添加一个新的key和value,value可以默认为空
	bool addValue(const std::string &section, const std::string &key, const std::string &value = "");
	bool addLongValue(const std::string &section, const std::string &key, const long value = 0);
	bool addDoubleValue(const std::string &section, const std::string &key, const double value = 0.0);
	bool addBoolValue(const std::string &section, const std::string &key, const bool value = false);

	// 修改value,如果key不存在,则会创建key和value
	bool setValue(const std::string &section, const std::string &key, const std::string &value);
	bool setLongValue(const std::string &section, const std::string &key, const long value = 0);
	bool setDoubleValue(const std::string &section, const std::string &key, const double value = 0.0);
	bool setBoolValue(const std::string &section, const std::string &key, const bool value = false);

	// 删除key
	bool deleteKey(const std::string &section, const std::string &key);
	// 删除key,如果最后一个key也被删除了,那么section也会被一起删除掉
	bool deleteKeys(const std::string &section, const std::string &key, const bool deleteSectionIfEmpty = true);
	// 删除section,整个section和其中的所有键值
	bool deleteSection(const std::string &section);


	// 获取string类型值
	std::string getValue(const std::string &section, const std::string &key, const std::string &defualtValue = "");
	// 获取char类型值
	char getValueC(const std::string &section, const std::string &key, const char &defualtValue = '\0');
	// 获取long、int、short类型
	long getLongValue(const std::string &section, const std::string &key, const short &defualtValue = -1);
	// 获取double、float类型
	double getDoubleValue(const std::string &section, const std::string &key, const double &defualtValue = 0.0);
	// 获取bool类型
	bool getBoolValue(const std::string &section, const std::string &key, const bool &defualtValue = false);

	// 获取section里有多少值
	int getSectionSize(const std::string &section);

	// 遍历所有
	void printAll();
    
private:
    bool _isloaded;		// 是否已经加载
	CSimpleIniA _ini;	// ini操作对象
};

#endif	// _COMMON_INICONFIG_H_

iniconfig.cpp

这个是封装simpleini的cpp文件内容

#include "iniconfig.h"

#include <stdio.h>
#include <iostream>


Iniconfig::Iniconfig() : _isloaded(false) {
	_ini.SetUnicode(true);		// 使用utf8编码
	_ini.SetMultiKey(false);	// 不允许一个key对应多个value

	_isloaded = false;
}

Iniconfig::Iniconfig(const std::string & path, st_env_config &config) {
	_ini.SetUnicode(true);		// 使用utf8编码
	_ini.SetMultiKey(false);	// 不允许一个key对应多个value
	
	_isloaded = false;

	SI_Error rc;
	rc = _ini.LoadFile(path.c_str());	// 另一种方式:SI_Error LoadFile(FILE * a_fpFile);
	if (rc < 0) {
		printf("加载 %s ini 文件失败!\n", path.c_str());
		_isloaded = false;
		return;
	} 

	int _int = getLongValue("section", "_int", -1);
	long _long = getLongValue("section", "_long", -1);
	double _double = getDoubleValue("section", "_double", 0.0);
	float _float = getDoubleValue("section", "_float", 0.0);
	bool _bool = getBoolValue("section", "_bool", false);
	std::string _string = getValue("section", "_string", "");
	char _char = getValueC("section", "_char", '\0');
	std::string ip = getValue("server", "ip", "0.0.0.0");
	unsigned short port = getLongValue("section", "port", -1);

	config = st_env_config(_int, _long, _double, _float, _bool, _string, _char, ip, port);

	_isloaded = true;
}

Iniconfig::~Iniconfig() {
    
}

// 加载ini文件
bool Iniconfig::loadfile(const std::string &path) {
   
    if (false == _isloaded) {
		SI_Error rc;
		rc = _ini.LoadFile(path.c_str());	// 另一种方式:SI_Error LoadFile(FILE * a_fpFile);
		if (rc < 0) {
			printf("加载 %s ini 文件失败!\n", path.c_str());
			_isloaded = false;
			return _isloaded;
		}

		_isloaded = true;

    } 
       
    return _isloaded;
}

bool Iniconfig::saveFile(const std::string & fileName) {

	SI_Error rc = _ini.SaveFile(fileName.c_str());
	if (rc < 0) {
		printf("保存 %s ini文件失败\n", fileName.c_str());
		return false;
	}

	_isloaded = false;

	return true;
}

void Iniconfig::setUnicode(const bool utf8) {
	_ini.SetUnicode(utf8);		// true:使用utf8编码
}

void Iniconfig::setMultiKey(const bool multKey) {
	_ini.SetMultiKey(multKey);	// false:不允许一个key对应多个value
}

bool Iniconfig::getData(st_env_config & config) {
	if (true == _isloaded) {
		int _int = getLongValue("section", "_int", -1);
		long _long = getLongValue("section", "_long", -1);
		double _double = getDoubleValue("section", "_double", 0.0);
		float _float = getDoubleValue("section", "_float", 0.0);
		bool _bool = getBoolValue("section", "_bool", false);
		std::string _string = getValue("section", "_string", "");
		char _char = getValueC("section", "_char", '\0');
		std::string ip = getValue("server", "ip", "0.0.0.0");
		unsigned short port = getLongValue("section", "port", -1);

		config = st_env_config(_int, _long, _double, _float, _bool, _string, _char, ip, port);

		return true;
	}

	return false;
}

std::string Iniconfig::getIniStr() {
	std::string str = "";

	if (true == _isloaded) {
		SI_Error rc = _ini.Save(str);
		if (rc < 0) {
			printf("获取ini文件字符串失败!\n");
			str = "";
		}
	}

	return str;
}

bool Iniconfig::addSection(const std::string & section) {

	if (false == _isloaded) { return false; }

	SI_Error rc = _ini.SetValue(section.c_str(), nullptr, nullptr);
	if (rc < 0) {
		printf("添加 %s 节点失败!\n", section.c_str());
		return false;
	}

	return true;
}

bool Iniconfig::addValue(const std::string & section, const std::string & key, const std::string & value) {
	if (false == _isloaded) { return false; }

	SI_Error rc = _ini.SetValue(section.c_str(), key.c_str(), value.c_str());
	if (rc < 0) {
		printf("添加 %s key失败!\n", key.c_str());
		return false;
	}

	return true;
}

bool Iniconfig::addLongValue(const std::string & section, const std::string & key, const long value) {
	if (false == _isloaded) { return false; }

	SI_Error rc = _ini.SetLongValue(section.c_str(), key.c_str(), value);
	if (rc < 0) {
		printf("添加 %s key失败!\n", key.c_str());
		return false;
	}

	return true;
}

bool Iniconfig::addDoubleValue(const std::string & section, const std::string & key, const double value) {
	if (false == _isloaded) { return false; }

	SI_Error rc = _ini.SetDoubleValue(section.c_str(), key.c_str(), value);
	if (rc < 0) {
		printf("添加 %s key失败!\n", key.c_str());
		return false;
	}

	return true;
}

bool Iniconfig::addBoolValue(const std::string & section, const std::string & key, const bool value) {
	if (false == _isloaded) { return false; }

	SI_Error rc = _ini.SetBoolValue(section.c_str(), key.c_str(), value);
	if (rc < 0) {
		printf("添加 %s key失败!\n", key.c_str());
		return false;
	}

	return true;
}

bool Iniconfig::setValue(const std::string & section, const std::string & key, const std::string & value) {
	if (false == _isloaded) { return false; }

	SI_Error rc = _ini.SetValue(section.c_str(), key.c_str(), value.c_str());
	if (rc < 0) {
		printf("修改 %s value失败!\n", value.c_str());
		return false;
	}

	return true;
}

bool Iniconfig::setLongValue(const std::string & section, const std::string & key, const long value) {
	if (false == _isloaded) { return false; }

	SI_Error rc = _ini.SetLongValue(section.c_str(), key.c_str(), value);
	if (rc < 0) {
		printf("修改 %s key失败!\n", key.c_str());
		return false;
	}

	return true;
}

bool Iniconfig::setDoubleValue(const std::string & section, const std::string & key, const double value) {
	if (false == _isloaded) { return false; }

	SI_Error rc = _ini.SetDoubleValue(section.c_str(), key.c_str(), value);
	if (rc < 0) {
		printf("修改 %s key失败!\n", key.c_str());
		return false;
	}

	return true;
}

bool Iniconfig::setBoolValue(const std::string & section, const std::string & key, const bool value) {
	if (false == _isloaded) { return false; }

	SI_Error rc = _ini.SetBoolValue(section.c_str(), key.c_str(), value);
	if (rc < 0) {
		printf("修改 %s key失败!\n", key.c_str());
		return false;
	}

	return true;
}

bool Iniconfig::deleteKey(const std::string & section, const std::string & key) {
	if (false == _isloaded) { return false; }

	bool done = false;

	// 删除 key
	done = _ini.Delete(section.c_str(), key.c_str());
	if (false == done) {
		printf("删除 %s - %s 失败!\n", section.c_str(), key.c_str());
		return false;
	}

	return true;
}

bool Iniconfig::deleteKeys(const std::string & section, const std::string & key, const bool deleteSectionIfEmpty) {
	if (false == _isloaded) { return false; }

	bool done = false;

	done = _ini.Delete(section.c_str(), key.c_str(), deleteSectionIfEmpty);
	if (false == done) {
		printf("删除 %s - %s 失败!\n", section.c_str(), key.c_str());
		return false;
	}

	return true;
}

bool Iniconfig::deleteSection(const std::string & section) {
	if (false == _isloaded) { return false; }

	bool done = false;

	done = _ini.Delete(section.c_str(), nullptr);
	if (false == done) {
		printf("删除整个 %s 和其下的所有 键 失败 !\n", section.c_str());
		return false;
	}

	return true;
}

std::string Iniconfig::getValue(const std::string & section, const std::string & key, const std::string & defualtValue) {
	if (false == _isloaded) { return ""; }

	return  _ini.GetValue(section.c_str(), key.c_str(), defualtValue.c_str());
}

char Iniconfig::getValueC(const std::string & section, const std::string & key, const char & defualtValue) {
	if (false == _isloaded) { return '\0'; }

	std::string str = std::to_string(defualtValue);
	return  _ini.GetValue(section.c_str(), key.c_str(), str.c_str())[0];
}

long Iniconfig::getLongValue(const std::string & section, const std::string & key, const short & defualtValue) {
	if (false == _isloaded) { return -1; }

	return  _ini.GetLongValue(section.c_str(), key.c_str(), defualtValue);
}

double Iniconfig::getDoubleValue(const std::string & section, const std::string & key, const double & defualtValue) {
	if (false == _isloaded) { return -1.0; }

	return  _ini.GetDoubleValue(section.c_str(), key.c_str(), defualtValue);
}

bool Iniconfig::getBoolValue(const std::string & section, const std::string & key, const bool & defualtValue) {
	if (false == _isloaded) { return false; }

	return  _ini.GetBoolValue(section.c_str(), key.c_str(), defualtValue);
}

int Iniconfig::getSectionSize(const std::string & section) {
	if (false == _isloaded) { return -1; }

	return _ini.GetSectionSize(section.c_str());
}

void Iniconfig::printAll() {
	CSimpleIniA::TNamesDepend sections;
	// get all sections
	_ini.GetAllSections(sections);
	// 遍历所有 section 的 key 和 value
	for (const auto &it : sections) {
		const CSimpleIniA::TKeyVal *pKeyVal = _ini.GetSection(it.pItem);
		if (nullptr != pKeyVal) {
			for (const auto& it : *pKeyVal) {
				std::cout << it.first.pItem << " = " << it.second << std::endl;
			}
		}
	}
}

测试代码:

st_env_config config;
Iniconfig cof(FILE_NAME, config);


cof.addSection("abc");
cof.addValue("abc", "name", "a");
cof.addBoolValue("abc", "vip", true);
cof.addDoubleValue("abc", "length", 175.5);
cof.addLongValue("abc", "weight", 85);

cof.setValue("abc", "name", "b");
cof.setBoolValue("abc", "vip", false);
cof.setDoubleValue("abc", "length", 188.8);
cof.setLongValue("abc", "weight", 90);

//cof.deleteKey("abc", "name");
//cof.deleteKeys("abc", "vip");
//cof.deleteSection("abc");

printf("name = %c\n", cof.getValueC("abc", "name"));
printf("name = %s\n", cof.getValue("abc", "name").c_str());
printf("bool = %d\n", cof.getBoolValue("abc", "vip"));
printf("lenght = %f\n", cof.getDoubleValue("abc", "length"));
printf("weight = %ld\n", cof.getLongValue("abc", "weight"));

printf("%s\n", cof.getIniStr().c_str());
cof.saveFile(FILE_NAME);

五、总结

simpleini库的基本用法如上面展示的那样,具体还有一些其他的api,现在还用不到,等用到了,再来补充!

simpleini这个库应该也不算难,无非就是GetValue和SetValue的使用!

ini文件常用来初始化程序,例如存储一些软件启动时初始化的一些基础数据,学习完这个库后,日后如果有写一些小软件就可以使用ini去初始化了!

SimpleIni:非常简单的类来管理 .ini 或 .conf 等配置文件 简单信息 非常简单的类来管理 .ini 或 .conf 等配置文件。 介绍 此类允许您使用不到 10 种方法轻松管理配置文件。 要使用,请在您的项目中包含 SimpleIni.cpp 和 SimpleIni.h。 特征 获取和设置键的值 获取和设置评论 浏览部分和键 由 ; 标识的评论或者 # 删除部分、键和值周围的空白。 不支持多行值。 在保存方法期间,剖面线上的注释会丢失。 在 Linux 和 Windows、Intel 或 ARM 上编译。 可移植性 单元测试成功通过: Windows 7(CPU 英特尔赛扬) Linux Ubuntu(CPU Intel Atom) Raspberry Pi (CPU ARM) 上的 Linux Raspian NAS DNS-320 (CPU ARM) 上的 Linux FunPlug(编译指令定义 LINUX 或 WIN 仅对单 立即下载

相关推荐

INI配置文件操作库SimpleIni.zip

SimpleIni 是一个跨平台的 C 库,提供一个简单的API用于操作 ini 配置文件。支持ANSII,MBCS以及Unicode编码.在Windows WinCE和Linux上通过测试.支持多行值和多个同名健. 标签:SimpleIni

simpleini图文讲解

目录 简介 注意事项 ini数据加载和输出 字符集自动转换 API 文记录simpleini 的使用心得,篇幅较小,主要总结其中的重点部分,以文字和图表的方式叙述。 简介 simpleini是C++对ini格式数据的解析/生成库。我比较推荐,理由可看介绍https://github.com/brofield/simpleini,其中我比较看重以下几个优点: simple...

kongds的博客 2686

AI应用安全 - Prompt注入攻击

随着大模型的爆火,各行各业都在使用大模型进行智能化改造。但是如何做一个可靠的大模型应用,就需要考虑各种安全问题。本文主要介绍一种常见的安全问题,即prompt注入攻击,并介绍一些防范手段。Prompt Injection Attack(提示注入攻击)是针对大型语言模型(LLM)的一种新兴安全威胁,攻击者通过精心构造的输入提示(prompt)来操纵模型行为,使其产生非预期输出或执行恶意操作。它主要包括两种注入方式,一是直接注入,而是间接注入。

sinat_28694519的博客 1932

Simpleini框架的使用

Simpleini框架的使用

葛雨龙的博客 653

别再死记硬背了!用TwinCAT 3手把手教你配置EtherCAT伺服驱动的PDO映射(DS402协议)

本文详细介绍了如何使用TwinCAT 3配置EtherCAT伺服驱动的PDO映射(DS402协议),涵盖环境准备、设备扫描、PDO映射实战及高级技巧。通过具体操作步骤和常见问题排查,帮助工程师快速掌握EtherCAT通信配置,提升运动控制系统的效率和稳定性。

weixin_29185493的博客 321

PayPal支付集成完全指南:开源库实践

本文介绍了如何从零开始集成PayPal支付功能。首先概述了PayPal提供的多语言SDK和开源库,包括PHP、Python、Node.js等版本。然后详细说明了准备工作,包括注册开发者账号、获取API凭证和使用沙盒环境测试。文章以Node.js为例,演示了安装SDK、基础配置和实现支付流程的完整代码,包括创建订单和捕获支付两个核心功能。最后提及了订阅支付等高级功能,为开发者提供了完整的支付集成方案。通过清晰的代码示例和步骤说明,帮助开发者快速实现PayPal支付功能集成。

2501_93501927的博客 1257

C++操作配置文件.ini (***)

此次操作*.ini文件用到的工具:simpleini,下载地址:https://github.com/brofield/simpleini。原文链接:https://blog.youkuaiyun.com/cpp_learner/article/details/128780799。2. iniparser:这是C语言的库,挺方便使用的,开源,两个.h文件和两个.c文件,但只能在Linux中使用;3. simpleini:这是C++的库,挺方便使用的,跨平台,开源,就两个.h文件和一个.c文件,且支持中文;

ken2232的博客 380

如何编译RustDesk(Unbuntu 和Android版本)

备注:官方文档上,一边都是基于sciter,这个在后面已经不建议使用了,但是依然可以编译刚开始的时候看官方的文档,涉及的东西比较多,也搞的一头雾水,通过B站上一个视频,可以通过CI/CD来编译,以及act本地试试(最终放弃,大概需要下载大几十G的容器下来)。最终总算明确了方向,可以用自动化流水线来编译。直接看CI/CD的脚本文件文件在.github/workflows目录下,重点研究 bridge.yml 和flutter-build.yml 这两个文件。

lvronglee的专栏 2547

【亲测免费】 探索SimpleINI:一个简洁易用的配置文件处理库

在软件开发中,配置文件起着至关重要的作用,它们用于储存应用程序的设置和参数。是一个轻量级、跨平台的C++库,专门设计用于读写.ini配置文件,它以简单直观的API简化了与这些文件交互的过程。 ## 项目简介 SimpleINI由Brofield开发并维护,它提供了一种高效的方式来处理常见的配置文件任务,如读取、写入和更新.ini文件。无论你是新手还是经验丰富的开发者,这个库都能让你轻松地管理应...

gitblog_00083的博客 920

C/C++小宇宙代码(完整代码)

C语言实现小宇宙的完整代码。

AIGC 2523

python实现边缘检测Canny算子 (附完整源码)

python实现边缘检测Canny算子 (附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 456

simpleini 常见函数使用

simpleini使用 SimpleIni 是一个跨平台的 C++ 库,支持Windows, WinCE and Linux系统。直接上下载地址:https://github.com/brofield/simpleini 调用是直接包含头文件即可。因为开源库iniparser不支持Section大写,并且Key会变成小写,表示弃用。 基础函数调用 满足常规用途 写入ini文件 #include "SimpleIni.h" CSimpleIniA ini; int res = ini.Load

wybkobe的博客 1371

镜头调焦的 调整的是焦距还是像距?

在镜头 “调焦”(即日常拍照时的)中,调整的核心是,而非焦距。

AIoT深度探索者 | 嵌入式系统架构师 深耕物联网(IoT)与人工智能(AI)融合技术,聚焦​​边缘计算、图像开发、低功耗通信协议​​,致力于智能硬件,关注我获取最新技术文章信息与海量资源~ 1350

C++ini文件操作

C++ ini文件读写操作整理;

Yry01的博客 3293

三菱FX5U气缸控制功能块(完整ST源代码+示例程序)

如果机器包含100个气缸,我们只需要修改数组的元素数量就可以了,效率非常的高。待续....博途PLC 面向对象系列之“双通气缸功能块“(SCL代码)_plc面向对象-优快云博客文章浏览阅读667次。本文介绍了博途PLC中面向对象编程的应用,重点讲解了双通气缸的功能块设计,包括双通电磁阀功能块、双通气缸的UDT数据类型以及SCL代码实现。同时,对比了双通与单通电磁阀的差异,并讨论了将单通气缸改造为双通气缸的方法,强调了双通气缸在安全性上的优势。

RXXW_Dor的博客 1026

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

c++中解析ini 文件的simpleIni库

simpleIni库简介: 一个跨平台库,它提供了一个简单的 API 来读取和写入 INI 样式的配置文件。 它支持 ASCII、MBCS 和 Unicode 中的数据文件。它被明确设计为可移植到任何平台, 并已在Windows,WinCE和Linux上进行了测试。使用MIT许可证以开源和免费的方式发布。 功能: 1】加载和保存 INI 样式的配置文件 2】自由接受文件格式 3】支持char或wchar_t变成接口 4】通过用户编写的转换器类支持非标准字符类型或文件编码 5】支持以编程方...

c4679281314的博客 3258

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

ini配置文件&解析(C++)

ini解析学习文档 一.什么是Ini ​ ini文件是Initialization File的缩写,即初始化文件,通常存放的是一个程序的初始化信息,是Windows的系统配置文件所采用的存储格式,统管windows的各项配置。ini文件的后缀名不一定是.ini,也可以是**.cfg、.conf或者是.txt**。 二.ini文件格式&语法规范 ​ **ini文件由若干个节(section)组成,每个section由若干键(Key)组成,每个Key可以赋相应的值。读写ini文件实际上就是读写某个的s

S—WORKS宇 1万+

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

c++之ini配置文件的详细解析

本文对如何使用ini配置文件进行了详细解析。其次详细解析'\0','\n','\r'的使用。

zxy_ZXY123的博客 3955

SimpleIni函数总结

void Reset();    //释放内存中存储的对象     //      设置INI数据的存储格式,参数为true时保存为UTF-8格式,否则为本地编码格式 void SetUnicode(bool a_bIsUtf8 = true); //获取INI数据的存储格式(是否为Unicode (UTF-8)) bool IsUnicode() const;     //是

IT小菜鸟 5540

C++实用工具类-ini配置文件解析

介绍C++常用工具代码-ini配置文件的解析读取实现代码, 通过内部状态流转+二级map方式实现, 轻量易用

xiaoqiang321的专栏 2134

如何使用SimpleIni:C++开发者必备的跨平台INI配置文件解析库

SimpleIni是一款轻量级的跨平台C++库,提供简单易用的API来读取和写入INI风格的配置文件。无论是在Windows、Linux还是macOS系统上,开发者都能通过它轻松处理应用程序的配置数据,实现配置文件的高效管理。 ## 📚 什么是SimpleIni? SimpleIni作为一款专注于INI文件处理的C++库,其核心功能是实现INI配置文件的加载、解析、修改和保存。它采用单头文件

gitblog_01135的博客 769

读写ini配置文件(C++)

读写ini配置文件(C++)

NRWHF的博客 9384

通过C++操作ini文件

.ini文件是Initialization File的缩写,即初始化文件,是windows的系统配置文件所采用的文件类型。它可以存储程序的配置信息,有的时候我们也需要通过ini文件来存储一些程序配置信息或者数据信息,那么我们如何操作ini文件呢? 这里采用C++来演示操作ini文件,我们需要通过API来操作ini文件。 首先我们用到的头文件有 Windows.h *注意:更改ini文件必须包含此文件,不然无法使用API iostream conio.h string.h 需要用到的API函数有 W

zzxhh628的博客 5387

C++读取ini格式配置文件

[]方括号下面的为一个节,通过变量名索引后面的值。

ljjjjjjjjjjj的博客 1万+

C++之INI配置文件读写/注释库 inicpp 介绍【简单易用-包含inicpp.hpp头文件即可】

一个头文件(header-file-only)搞定INI文件读写、甚至进行注释。跨平台,并且用法极其简单。MIT license,从此配置INI文件就像喝水。【 注:对您有帮助的话,Star或Issues为项目维护提供动力,感谢。】 - by offical of JN-inicpp project.

大道之行,始于足下 2018

C++,ini文件操作(包含类)

什么是ini文件? initialization File,即为初始化文件,是windows的系统配置文件所采用的存储格式,统管windows的各项配置。或者作为项目中的配置文件,为整个项目所共用。 文件格式为 节、键、值。其中节为[Section name], 参数为 key(键)=value(值)。 ini文件中注解使用分号表示(;),在分号后面的文字,直到该行结尾都全部为注解。

爱她就要努力 4801
上一篇: Linux gcc/g++编译链接头文件和库(动态库.so 和 静态库.a)
下一篇: C++ Log4cpp跨平台日志库使用记录(Window与Linux)
cpp_learners
博客等级 码龄7年 1526粉丝 274原创
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpp_learners

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值