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

news2024/11/24 16:09:59

最近在学习时,发现自己还不会操作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去初始化了!

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

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

相关文章

Dubbo原理简介

Dubbo缺省协议采用单一长连接和NIO异步通讯&#xff0c;适合于小数据量大并发的服务调用&#xff0c;以及服务消费者机器数远大于服务提供者机器数的情况。 作为RPC&#xff1a;支持各种传输协议&#xff0c;如dubbo,hession,json,fastjson&#xff0c;底层采用mina,netty长连接…

SAP 分析云 2023.03 版新功能抢先看

本文介绍了 SAP 分析云2023.03版本的新功能。对于 SAP 分析云季度发布周期 (QRC) 客户&#xff0c;此版本及其功能将作为 QRC 2023 年第2季度版本的一部分提供。本版本主要在仪表盘和故事设计、数据集成、企业计划方面进行了功能更新&#xff0c;来和阿拓一起看看吧&#xff01…

Hive---窗口函数

Hive窗口函数 其他函数: Hive—Hive函数 文章目录Hive窗口函数开窗数据准备建表导入数据聚合函数window子句LAG(col,n,default_val) 往前第 n 行数据LEAD(col,n, default_val) 往后第 n 行数据ROW_NUMBER() 会根据顺序计算RANK() 排序相同时会重复&#xff0c;总数不会变DENSE…

C#要点技术(一) - List 底层源码剖析

1。 ## 常用组件底层代码解析List 底层代码剖析List是一个C#中最常见的可伸缩数组组件&#xff0c;我们常常用它来替代数组&#xff0c;因为它是可伸缩的&#xff0c;所以我们在写的时候不用手动去分配数组的大小。甚至有时我们也会拿它当链表使用。那么到底它的底层是怎么编写…

将Quazip编译成基于32位release版的库时报错的解决方案

开发环境&#xff1a;Win10 Qt5.9.9 注意&#xff1a;阅读本篇文章前&#xff0c;首先阅读Quazip的编译及使用&#xff0c;保姆级教程。 之前写了如何编译Quazip的库&#xff0c;当时是使用MSV2015-64-release来编译的&#xff0c; 具体编译流程可参考之前的文章Quazip的编译及…

3句代码,实现自动备份与版本管理

前言&#xff1a;服务器开发程序、测试版本等越来越多&#xff0c;需要及时做好数据的版本管理和备份&#xff0c;作为21世界的青年&#xff0c;希望这些事情都是可以自动完成&#xff0c;不止做了数据备份&#xff0c;更重要的是做好了版本管理&#xff0c;让我们可以追溯我们…

用Go快速搭建IM即时通讯系统

WebSocket的目标是在一个单独的持久连接上提供全双工、双向通信。在Javascript创建了Web Socket之后&#xff0c;会有一个HTTP请求发送到浏览器以发起连接。在取得服务器响应后&#xff0c;建立的连接会将HTTP升级从HTTP协议交换为WebSocket协议。由于WebSocket使用自定义的协议…

深度学习部署笔记(十): CUDA RunTime API-2.2流的学习

1. 流的定义 流&#xff08;Stream&#xff09;是一个基于上下文&#xff08;Context&#xff09;的任务管道抽象&#xff0c;是一组由GPU依次执行的CUDA操作序列&#xff0c;其中每个操作可能会使用或产生数据。在一个上下文中可以创建多个流&#xff0c;每个流都拥有自己的任…

Kettle体系结构及源码解析

介绍 ETL是数据抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;、装载&#xff08;Load&#xff09;的过程。Kettle是一款国外开源的ETL工具&#xff0c;有两种脚本文件transformation和job&#xff0c;transformation完成针对数据的基础转换&…

全网最详细的(CentOS7)MySQL安装

一、环境介绍 操作系统&#xff1a;CentOS 7 MySQL&#xff1a;5.7 二、MySQL卸载 查看软件 rpm -qa|grep mysql 卸载MySQL yum remove -y mysql mysql-libs mysql-common rm -rf /var/lib/mysql rm /etc/my.cnf 查看是否还有 MySQL 软件&#xff0c;有的话继续删除。 软件卸…

单线程的 javascript 如何管理任务

要怎么理解 JavaScript 是单线程这个概念呢&#xff1f;大概需要从浏览器来说起。 JavaScript 最初被设计为浏览器脚本语言&#xff0c;主要用途包括对页面的操作、与浏览器的交互、与用户的交互、页面逻辑处理等。如果将 JavaScript 设计为多线程&#xff0c;那当多个线程同时…

Excel职业版本(4)

图表 图表基本结构 组成元素 图表的分类 柱状图 介绍&#xff1a;在竖直方向比较不同类型的数据 适用场景&#xff1a;用于二维数据集&#xff0c;对于不同类型的数据进行对比&#xff0c;也可用于同一类型的数据在不同的时间维度的数据对比&#xff0c;通过柱子的高度来反…

GeniE 实用教程(五)荷载与边界

目 录一、前言二、位移边界三、工况与组合3.1 荷载工况3.2 荷载组合四、自重/设备/隔间4.1 结构自重4.2 设备荷载4.3 隔间负载五、显式荷载六、环境荷载6.1 点位信息 / Location6.2 波浪数据 / Wave6.2.1 规则波数据6.2.2 一般波数据6.3 洋流廓线 / Current Profile6.4 风轮廓线…

【物联网低功耗转接板】+机智云开发体验之遥控灯

在本文中&#xff0c;通过设计一个智能遥控的小灯来介绍一下使用机智云平台的开发过程和体验。一、硬件设计设计硬件电路之前&#xff0c;我先查阅了GE211的规格书&#xff0c;发现预留接口是5V电平。翻找了一下手头的板卡&#xff0c;发现只有一块arduino UNO是5V电平的。因此…

Linux驱动的同步阻塞和同步非阻塞

在字符设备驱动中&#xff0c;若要求应用与驱动同步&#xff0c;则在驱动程序中可以根据情况实现为阻塞或非阻塞一、同步阻塞这种操作会阻塞应用程序直到设备完成read/write操作或者返回一个错误码。在应用程序阻塞这段时间&#xff0c;程序所代表的进程并不消耗CPU的时间&…

buu RSA 1 (Crypto 第一页)

题目描述&#xff1a; 两个文件&#xff0c;都用记事本打开&#xff0c;记住用记事本打开 pub.key: -----BEGIN PUBLIC KEY----- MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAMAzLFxkrkcYL2wch21CM2kQVFpY97 /AvKr1rzQczdAgMBAAE -----END PUBLIC KEY-----flag.enc: A柪YJ^ 柛x秥?y…

Vue中 $attrs、$listeners 详解及使用

$attrs 用于父组件隔代向孙组件传值 $ listeners用于孙组件隔代向父组件传值 这两个也可以同时使用&#xff0c;达到父组件和孙组件双向传值的目的。 A组件&#xff08;App.vue&#xff09; <template><div id"app"><!-- 此处监听了两个事件&…

前端包管理工具:npm,yarn、cnpm、npx、pnpm

包管理工具npm Node Package Manager&#xff0c;也就是Node包管理器&#xff1b; 但是目前已经不仅仅是Node包管理器了&#xff0c;在前端项目中我们也在使用它来管理依赖的包&#xff1b; 比如vue、vue-router、vuex、express、koa、react、react-dom、axios、babel、webpack…

描述性统计

参考文献 威廉 M 门登霍尔 《统计学》 文章目录定性数据的描述方法条形图饼图帕累托图定量数据点图茎叶图频数分布直方图MINITAB 工具在威廉《统计学》一书将统计学分为描述统计学和推断统计学&#xff0c;他们的定义分别如下&#xff1a;描述统计学&#xff1a;致力于数据集的…

人生又有几个四年

机缘 不知不觉&#xff0c;已经来 csdn 创作四周年啦~ 我是在刚工作不到一年的时候接触 csdn 的&#xff0c;当时在学习 node&#xff0c;对 node 的文件相关的几个 api 总是搞混&#xff0c;本来还想着在传统的纸质笔记本上记一下&#xff0c;但是想想我大学记了好久的笔记本…