simpleini 常见函数使用:快速入门 (***)
simpleini 官方手册 (***)
simpleini图文讲解
使用SimpleIni解析ini文件
c++中解析ini 文件的simpleIni库 (**)
C/C++ 操作ini文件(SinpleIni 跨平台库) (比较完整 ****)
-----------------------------------------------
https://gitee.com/LiPeiLei/convertutf
-----------------------------------------------
QString 与 std::string 的相互转换方法 (**)
https://blog.youkuaiyun.com/ken2232/article/details/132415584
-----------------------------------------------
使用 simpleini 的意义:
1. Qt属于半商业性质的产品,开源社区版的功能,可用,但有些功能并不好用。都好用了,怎么赚钱?
比如:QSettings使用很简单,但是,linux版:Key的排列只按照 Unicode顺序;不会按照用户想要的顺序排列。因为它使用的是 QMap。
2. simpleini 的最新版,key的排序是按照语句的运行顺序,一般情况下,这才是我们想要的一种常用顺序。
3. simpleini、inih、iniparser:已收录在 debian的官方仓库。因此,其可靠性,还是值得信任的。
4. 在使用上,似乎比 Qt复杂一些。
实际上,如果只是使用这些第三方库的最基本的功能,这样和 QtSettings的区别也是不大的。
5. ConvertUTF.h : ensure that UTF32 is 32-bits on a 64-bit platform. It should still be 32 on a 32-bit platform even with this change.
应该是 simpleini 引用别人的三方库 ConvertUTF.h ?
6. Qt 内部运算只支持 utf8 ?
所以要加上这句:
ini.SetUnicode(); // 没有直接转为 utf8的方法。在 Qt中,可能还需要转为 utf8编码 ?
电脑桌面系统,可能会同时支持 utf8、utf16、utf32?
https://gitee.com/mirrors/simpleini
要点:
//与 Key有关的主要函数形式
返回值类型 不同名函数/同名重载函数 (session,key)
返回值类型 不同名函数/同名重载函数 (session,key,[或当失败时的]默认返回值)
//不同名函数
int _int = std::stoi(ini.GetValue("section", "_int", "-1"));
double _double = std::stod(ini.GetValue("section", "_double", "0.0"));
//同名函数,不同的返回值
std::string _string2 = ini.GetValue("section", "_string2", "");//[0]:表示指针,指向起始的首个字符。[1]:指向起始的第二个字符.
char _char = ini.GetValue("section", "_char", "")[0];
std::string ip = ini.GetValue("server", "ip", "0.0.0.0");//=========================================
simpleini 只有 char* 的返回值函数,没有 string 的返回值函数。
转换:char*-->string
直接赋值就行string s;
char* p ="hello";
s = p;
1. 三个文件
SimpleIni.h //主要文件
ConvertUTF.h // unicode支持
ConvertUTF.c
2. 官方:SIMPLE USAGE / 简明用法
// simple demonstration
CSimpleIniA ini;
//如果不指定,则可能是:utf8 /16/ 32 ,是这样吗 ?
ini.SetUnicode(); // SetUnicode(true); void setUnicode(const bool utf8 = true);
//打开文件
SI_Error rc = ini.LoadFile("example.ini");
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_OK);
//读值
const char* pv;
pv = ini.GetValue("section", "key", "default");
ASSERT_STREQ(pv, "value");
//写
ini.SetValue("section", "key", "newvalue");
//读值:如果“值”无效,则返回默认值:default
pv = ini.GetValue("section", "key", "default");
ASSERT_STREQ(pv, "newvalue");//===========================================
非官方手册:附加一些主要函数,来自官方手册。
setUnicode(); //utf8设置。void setUnicode(const bool utf8 = true);
setMultiKey(const bool multKey = false); //一键多值。void setMultiKey(const bool multKey = false);
SAVING DATA
std::string data;
rc = ini.Save(data); //保存到内存// save the data back to the file
rc = ini.SaveFile("example2.ini"); //保存到文件
评注:
1. simpleini 复杂吗?
单纯从上面的官方简明样例来看:复杂程度,似乎比 QSettings差不多。
但是,
1.1. 不知道在跨平台时,是否有问题?
2. simpleini 也可以很简单
的用法,可以和 QSettings一样简单。
也可以让人眼缭乱的复杂。
从功能上来看,QSettings可以视为是 simpleini 的子集。
当我们只用 simpleini 的子集时,就不会再觉得 simpleini 的复杂另外。
3.
CSimpleIniA ini;
const char* _char = ini.GetValue("section", "_char", "defa");
qDebug()<<"test-1: _char : "<<_char;
qDebug()<<"test-2 : *_char : "<<*_char;
///error: cannot initialize a variable of type 'char *' with an rvalue of type 'const char *'
//char* _char = ini.GetValue("section", "_char", "defa"); //error
char _char2 = ini.GetValue("section", "_char", "defa")[0];
qDebug()<<"test-3: _char2 : "<<_char2;
///error: indirection requires pointer operand ('int' invalid)
//qDebug()<<"test-4 : *_char2 : "<<*_char2; //error
输出结果:
test-1: _char : defa
test-2 : *_char : d
test-3: _char2 : d
评注:
1. 函数可以有多种的变形写法。
2. 还是按照官方的标准写法,要好一些吧?虽然没必要奇形怪状;但却是有局限性的,并不适合于某些的应用场景。
附注 1
// 设置INI数据的存储格式,参数为true时保存为UTF-8格式,否则为本地编码格式
void setUnicode(const bool utf8 = true);
// 是否允许一个关键字对应多个值,默认为允许;若不允许,则将最后一个值作为此关键字关联的值,其他删除
void setMultiKey(const bool multKey = false);
附注 2
官方资料, 来自::"SimpleIni.h"
SI_CHAR == char and SetUnicode(true)
//函数原型
void SetUnicode(bool a_bIsUtf8 = true) {
if (!m_pData) m_bStoreIsUtf8 = a_bIsUtf8;
}
附注 3
//与Qt 的区别:Qt读入文本,然后,再进行类型转换。
// simpleini:直接在函数参数中指定了数据的类型;以及默认的返回值。
int _int = std::stoi(ini.GetValue("section", "_int", "-1"));
printf("_int = %d\n", _int);
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());
3. C++ C 混合编译不要忘记 (不需要了)
#ifdef __cplusplus
extern "C" {
#endif
/*实现 */
#ifdef __cplusplus
}
#endif
注:
1. 本身就是用 cpp写的。不需要了?
// SimpleIni.h
template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
class CSimpleIniTempl
{
2. C++和C的混合编译
__cplusplus 宏,这是C++中已经定义的宏,是用来识别编译器的,也就是说,将当前代码编译的时候,是否将代码作为 C++ 进行编译。
https://blog.youkuaiyun.com/qq_61313949/article/details/124516395
============================
主要函数
3. 增
SetValue
参数一:节点
参数二:键
参数三:值
返回值:SI_Error (也就是int类型)// 添加一个新的 section
rc = ini.SetValue("section1", nullptr, nullptr);-----------------
6. 查
GetValue
参数一:节点
参数二:键
参数三:如果没找到,返回参数三指定的默认值
返回值:const char *std::string _string = ini.GetValue("section", "_string", "");
printf("_string = %s\n", _string.c_str());-----------------
5. 删
Delete
参数一:节点
参数二:键
返回值:boolbool done = false;
1). 删除 key 和 value
// 删除 key
done = ini.Delete("section1", "name");
-----------------修改值(value)
// 修改value,如果键(name)不存在则添加该 key和value
rc = ini.SetValue("section1", "name", "李四");-----------------
5). 获取一个键对应多个值
首先,ini.SetMultiKey(true);得设置为true,
否则只会获取到最后一个值,其他会被删除掉;-----------------
6). 获取指定节点(section)里有多少键值
// 获取section里有多少值
int size = ini.GetSectionSize("section");
printf("section 的 key 个数:%d\n", size)===============
// 加载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);-----------------
// 获取string类型值
std::string getValue(const std::string §ion, const std::string &key, const std::string &defualtValue = "");
// 获取char类型值
char getValueC(const std::string §ion, const std::string &key, const char &defualtValue = '\0');
// 获取long、int、short类型
-----------------
-----------------------------------------------
开源 fifo_map:C++实现的支持插入顺序的高效map (***)
开源 fifo_map:C++实现的支持插入顺序的高效map (***)_ken2232的博客-优快云博客
C/C++ 操作ini文件(SinpleIni 跨平台库) (比较完整 ****)
https://blog.youkuaiyun.com/cpp_learner/article/details/128780799
----------------------
simpleini项目地址:cpp库
https://github.com/brofield/simpleini
下载:debian Folder: 4.20+dfsg-1| Debian Sources
inih : c库
下载:debian Folder: 55-1| Debian Sources
iniparser
下载:debian Folder: src| Debian Sources
---------------------------------
为什么出现在可信的、主流 linux发行版中的 ini读写库,是可信的呢?
主流 linux 开发社区:当然希望有更多的程序员来免费帮它们开发 app,或者将 app移植到该操作系统 OS中了。
因此,linux发行版:当然需要做一些必要的、基础的软件支持工作。
假如那些与操作系统有关的 app,发行者不提供,由程序员自己来处理,那么,还有多少程序员有兴趣将自己的作品移植到这种操作系统中呢?
要知道,在跨语种的移植中,与之相应的 app移植,可能是很麻烦的、或者很耗时的,甚至是只能由操作系统开发者来完成这类工作,才是最合理和恰当的。
而 ini配置文件,是大部分 app都会有的,因此,使用可信的、主流 linux发行版中的 ini读写库,是一种比较理想的选择。
至少:软件作者进行了测试;主流 linux发行版社区、进行了筛选,并且也进行了测试。
在同一个发行版上,同一个开源软件,并不见得可以适配该发行版的所有版本,因此,需要修改。而这类修改,往往都是由 OS社区来、或才能完成的。
===========================
simpleini 常见函数使用:快速入门 (***)
简评:
有些文字,太过于长篇。从这篇文章来看,其实 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.LoadFile("test.ini");
if (res < 0)
return res ;
ini.SetValue("Setting", "server", "192.168.1.1");
ini.SetLongValue("Setting", "port", 80);
ini.SetValue("Setting", "username", "admin");
ini.SetValue("Setting", "password", "admin");
ini.SetDoubleValue("Data", "width", 10.0);
// .toUtf8()
res = ini.SaveFile(gCloudIniPath.c_str()); //gCloudIniPath.c_str():to FullFileName /return res ;
读取ini文件
#include "SimpleIni.h"
CSimpleIniA ini;
int res = ini.LoadFile("test.ini");
if (res < 0)
return res ;
unsigned short port = ini.GetLongValue("Setting","port",0);
const char * pVal = ini.GetValue("Setting", "username", "admin");//可赋值出来
const char * xVal = ini.GetValue("Setting", "password", "admin");
ini.Delete("Data", "width");
res = ini.SaveFile("test.ini");
return res ;
————————————————
版权声明:本文为优快云博主「划水的咸鱼混日子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/wybkobe/article/details/112382361
simpleini 图文讲解
目录
简介
注意事项
ini数据加载和输出
字符集自动转换
API
Demo
文记录simpleini 的使用心得,篇幅较小,主要总结其中的重点部分,以文字和图表的方式叙述。
简介
simpleini是C++对ini格式数据的解析/生成库。我比较推荐,理由可看介绍https://github.com/brofield/simpleini,其中我比较看重以下几个优点:
- simpleini库仅由SimpleIni.h一个文件组成。
- simpleini库支持char和wchar_t字符编程。 //支持 Unicode,如中文
- 可选支持多行的value和重复的key名称。
- 可选支持不区分大小写的section和key。
- 支持key/value可以没有对应的section。
- 支持section和key可以按照加载时的顺序获取。 // Qt只支持 Unicode排序
- simpleini库加载或输出数据时,支持UTF-8字符集和MBCS(本地语言)字符集。
- simpleini库解析ini数据前,若使用wchar_t接口,自动将ini数据的字符集转换为当前字符集。
缺点:
- simpleini库加载ini格式数据前,不支持自动识别字符集,必须在加载数据前显式指明数据源的字符集。
- simpleini库加载和输出数据时,仅支持UTF-8和MBCS(本地语言)字符集,而其他字符集暂不支持。( // Qt好像也是这样的吧?UTF-8是 Qt内部运算的默认编码,这样似乎也没有问题吧?)
注意事项
解析ini数据时,注意字符集的自动转换。如果当前使用char接口,则输入数据没有发生字符集转换,字符集保持不变(加载的数据是UTF-8/ MBCS字符集,则保存相应字符集的数据)。如果当前使用wchar_t接口,则输入数据的字符集(UTF-8/MBCS)自动转换为UTF-16/32字符集。
当使用wchar_t接口时,由于加载数据和输出数据时都会自动转换字符集,因此输出数据时,字符集被还原回来了,即输出数据的字符集始终与原始数据的字符集保持一致。
ini数据加载和输出
字符集自动转换
API
重点了解ini数据加载和输出,以及字符集自动转换。API的熟悉只需多用即可,simpleini的API也是类似DOM,因此也简单易用。
Demo
// 不区分大小写
CSimpleIni ini;
CSimpleIni::TNamesDepend sections;
ini.GetAllSections(sections);
sections.sort(typename CSimpleIni::Entry::LoadOrder()); // 按照加载时的顺序排序
for (const auto &it : sections)
{
const CSimpleIni::TKeyVal *pKeyVal = ini.GetSection(it.pItem);
if (nullptr != pKeyVal)
{
for (const auto& it : *pKeyVal)
{
cout << it.first.pItem << _T(" = ") << it.second << endl;
}
}
}
————————————————
版权声明:本文为优快云博主「kds怪獸」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/kds0714/article/details/89457316
使用SimpleIni解析ini文件
SimpleIni 是一个跨平台的 C++ 库,支持Windows, WinCE and Linux系统,提供一个简单的API用于操作 ini 配置文件。
simpleini项目地址:
https://github.com/brofield/simpleini
一、Simpleini Api讲解
void Reset(); //释放内存中存储的对象
void SetUnicode(bool a_bIsUtf8 = true);//设置INI数据的存储格式,参数为true时保存为UTF-8格式,否则为本地编码格式
bool IsUnicode() const;//获取INI数据的存储格式(是否为Unicode (UTF-8))
void SetMultiKey(bool a_bAllowMultiKey = true);//是否允许一个关键字对应多个值,默认为允许;若不允许,则将最后一个值作为此关键字关联的值
bool IsMultiKey() const;//获取INI数据的存储格式(是否为一键多值)
void SetMultiLine(bool a_bAllowMultiLine = true);//设置数值能否跨越多行
bool IsMultiLine() const;//查询多行数据的状态
SI_Error LoadFile( const char * a_pszFile);//从磁盘加载INI文件到内存中,参数为INI文件的有效路径,返回错误定义
SI_Error LoadFile(const SI_WCHAR_T * a_pwszFile);//从磁盘加载INI文件(UTF-16)到内存中,参数为INI文件的有效路径,返回错误定义
SI_Error LoadFile(FILE * a_fpFile);//从一个文件指针加载INI文件,返回错误定义
SI_Error Load(std::istream & a_istream);//从输入流中加载INI文件,返回错误定义
SI_Error Load(const std::string & a_strData);//从std::string中加载INI文件,返回错误定义
SI_Error Load(const char * a_pData,size_t a_uDataLen);//从内存中加载INI文件,a_pData为要加载的数据,a_uDataLen为要加载的数据的长度,返回错误定义
SI_Error SaveFile(const char * a_pszFile,bool a_bAddSignature = true) const;//从内存INI文件保存到磁盘,a_pszFile为保存的有效路径,不是UTF-8时a_bAddSignature将忽略
SI_Error SaveFile(const SI_WCHAR_T * a_pwszFile,bool a_bAddSignature = true) const;//从内存INI文件(UTF-16)保存到磁盘,a_pszFile为保存的有效路径,不是UTF-8时a_bAddSignature将忽略
SI_Error SaveFile(FILE * a_pFile,bool a_bAddSignature = false) const;//将INI数据保存至一个文件中,a_pFile为二进制打开的文件描述符
SI_Error Save(OutputWriter & a_oOutput,bool a_bAddSignature = false) const;//保存INI数据。这些数据将被写入到输出设备
SI_Error Save(std::ostream & a_ostream,bool a_bAddSignature = false) const;//将INI数据保存到一个ostream
SI_Error Save(std::string & a_sBuffer,bool a_bAddSignature = false) const;//追加到一个字符串的INI数据
void GetAllSections(TNamesDepend & a_names) const;//检索所有的section名。这份名单是返回一个STL的list,a_names(list)接收所有的节名称
bool GetAllKeys(const SI_CHAR * a_pSection,TNamesDepend & a_names) const;//获取一个section下的所有关键字,结果保存在a_names中。返回true表示section找到,false表示未发现
bool GetAllValues(const SI_CHAR * a_pSection,const SI_CHAR * a_pKey,TNamesDepend & a_values) const;//获取一个指定section和关键字key下的所有值,保存在a_values。返回true表示找到,false表示未发现section/key
int GetSectionSize(const SI_CHAR * a_pSection) const;//获取指定section的key的个数,-1表示section不存在于INI文件中,其他表示个数
const TKeyVal * GetSection(const SI_CHAR * a_pSection) const;//返回一个section的键值对,用map保存
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;//获取一个特定的key值。如果启用了多个键(见SetMultiKey),那么只有第一个与该键关联的值返回; 参数a_pDefault是如果没有找到将要返回的值,参数a_pHasMultiple可选收到通知,如果有这个key有多个条目
long GetLongValue(const SI_CHAR * a_pSection,const SI_CHAR * a_pKey,long a_nDefault = 0, bool * a_pHasMultiple = NULL) const;//获取一个特定的key值。如果启用了多个键(见SetMultiKey),那么只有第一个与该键关联的值返回; 参数a_nDefault是如果没有找到将要返回的值,参数a_pHasMultiple可选收到通知,如果有这个key有多个条目
bool GetBoolValue(const SI_CHAR * a_pSection,const SI_CHAR * a_pKey,bool a_bDefault = false, bool * a_pHasMultiple = NULL) const;//检索某个特定键的布尔值。如果启用了多个键(见SetMultiKey),那么只有第一个与该键关联的值返回。参数a_bDefault是如果没有找到将要返回的值,参数a_pHasMultiple可选收到通知,如果有这个key有多个条目
SI_Error SetValue(const SI_CHAR * a_pSection,const SI_CHAR * a_pKey,const SI_CHAR * a_pValue,const SI_CHAR * a_pComment = NULL);//添加或更新一个section或者key
@参数a_pSection组中添加或更新
@参数a_pKey键添加或更新。设置为NULL创建一个空的section
@参数a_pValue值来设置。设置为NULL,创建一个空的section
@参数a_pComment为注释
返回SI_Error错误定义
返回SI_UPDATED值更新
返回SI_INSERTED值是插入
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); //添加或更新一个section或者key ,最后一个参数a_bUseHex为true表示写入的值为十六进制,为false为十进制
SI_Error SetBoolValue(const SI_CHAR * a_pSection,const SI_CHAR * a_pKey,bool a_nValue,const SI_CHAR * a_pComment = NULL);//添加或更新一个bool值
bool Delete(const SI_CHAR * a_pSection,const SI_CHAR * a_pKey,bool a_bRemoveEmpty = false);//删除了整个section,或者一个section中的key。 注意:启用多个键时,这将删除该名称的所有键
@参数a_pSection 删除section中的键,如果 a_pKey是NULL,section整个删除
@参数a_pKey 从指定的section中删除一个key。设置为NULL删除整个section
@参数a_bRemoveEmpty 删除一个section中的key之后,如果section是空的了,此section是否可以删除
@返回true key或section被删除
@返回false key或section没有找到
二、实例
创建test.ini文件,内容如下:
[server]
root = 10.1.1.1
gc = 10.1.1.2
game = 10.1.1.3
#include <iostream>
#include <SimpleIni.h>
using namespace std;
int main()
{
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile("test.ini");
const char * pVal = ini.GetValue("server", "game", "default");
ini.SetValue("server", "game", "10.1.1.5");
const char * xVal = ini.GetValue("server", "game", "default");
cout << pVal << endl;
cout << xVal << endl;
// save the data back to the file
int rc = ini.SaveFile("test.ini");
if (rc < 0) return false;}
————————————————
版权声明:本文为优快云博主「byxdaz」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/byxdaz/article/details/88144895
c++中解析ini 文件的simpleIni库 (**)
https://blog.youkuaiyun.com/c4679281314/article/details/122951274
simpleIni库简介:
一个跨平台库,它提供了一个简单的 API 来读取和写入 INI 样式的配置文件。
它支持 ASCII、MBCS 和 Unicode 中的数据文件。它被明确设计为可移植到任何平台,
并已在Windows,WinCE和Linux上进行了测试。使用MIT许可证以开源和免费的方式发布。
功能:
1】加载和保存 INI 样式的配置文件
2】自由接受文件格式
3】支持char或wchar_t变成接口
4】通过用户编写的转换器类支持非标准字符类型或文件编码
5】支持以编程方式添加/修改值
6】简单编译,没有告警
如何使用编译:
下载网址: simpleini/README.md at master ·布罗菲尔德/简单尼 ·GitHub
simpleini · PyPI https://pypi.org/project/simpleini/
包含的文件: 红色中都是我们需要的:
创建个文件夹把这两个 ".h"包含在内然后再实现自己所需的cpp文件接口进行编译即可;
这三个文件可在 Window 或 Linux 环境去使用!
介绍的用法,Linux和Window环境均可使用!
https://blog.youkuaiyun.com/cpp_learner/article/details/128780799
C++ C混合编译不要忘记
#ifdef __cplusplus
extern "C" {
#endif
/*实现 */
#ifdef __cplusplus
}
#endif
INI文件示例:
[Cfg0]
Period = 5000
flag = 1
Num = 1
StartNum = 3
dlNum = 2
ulNum = 2
调用读取示例:
//c++示例
CSimpleIniA ini;
SI_Error rc; //结构在simpleIni.h中定义了
rc = cfgini.LoadFile("xxx.ini"); //加载文件
period = cfgini.GetLongValue ("Cfg0", "Period ", 5); //读取Cfg0节点中的 Period 属性,如果没有这个节点的话默认值是5;
// 类似的接口 GetDoubleValue GetBoolValue SetValue SetLongValue 等;
rc = cfgini.SetLongValue("Cfg0", "Period ", 6, "Period");
常用接口:
1、加载文件
// load from a data file
CSimpleIniA ini;
SI_Error rc = ini.LoadFile("example.ini");
2、获取值
ini.GetLongValue("Cfg0", "Period ", 5);
ini.GetValue("section1", "key99");
3、修改数据
ini.SetValue("section1", nullptr, nullptr);
rc = cfgini.SetLongValue("Cfg0", "Period ", 6, "Period");
4、删除数据
ini.Delete("Cfg0", "Period ");
done = ini.Delete("section2", nullptr);
5、保存数据
// save the data to a string
std::string data;
rc = ini.Save(data);
举例:
config.cpp用来实现我们需要用到的接口:
/******************************************************************************
config ini访问接口,提供最基本的读写访问
将此文件编译成动态包,此文件作为访问config.ini的实现开放接口在config.h中声明
其他调用需要连接编译出来的动态库并包含头文件config.h即可
******************************************************************************/
#include "SimpleIni.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "stdio.h"
typedef struct {
unsigned int Period;
unsigned int flag;
unsigned short dlNum;
unsigned char dlNums;
unsigned char rsv0;
unsigned short ulNum;
unsigned char ulNums;
unsigned char rsv1;
} CFG_INI_STRU;
CSimpleIniA cfgini;
SI_Error err; //这个枚举在SimpleIni.h中有定义
CFG_INI_STRU cfg[2];
int BSP_ConfigLoadAll(char * path)
{
err = cfgini.LoadFile(path);
return err;
}
/* 简单提供接口 */
void get_node(void)
{
cfg[0].transPeriod = cfgini.GetLongValue("Cfg0", "Period", 0);
cfg[0].enflag = cfgini.GetLongValue("Cfg0", "flag", 1);
cfg[0].dlSlotsNum = cfgini.GetLongValue("Cfg0", "dlNum", 3);
cfg[0].dlSymbolsNum = cfgini.GetLongValue("Cfg0", "dlNums", 10);
cfg[0].ulSlotsNum = cfgini.GetLongValue("Cfg0", "ulNum", 1);
cfg[0].ulSymbolsNum = cfgini.GetLongValue("Cfg0", "ulNums", 2);
printf("Period : %d \n", cfg[0].Period);
printf("flag : %d \n", cfg[0].flag);
printf("dlNum : %d \n", cfg[0].dlNum);
printf("Nums : %d \n", cfg[0].dlNums);
printf("ulNum : %d \n", cfg[0].ulNum);
printf("ulNums : %d \n", cfg[0].ulNums);
}
#ifdef __cplusplus
}
#endif
config.h 声明开发的接口
#ifndef CONFIG_INI_H
#define CONFIG_INI_H
int BSP_ConfigLoadAll(char * path);
void get_node(void);
#endif
config.ini 定义的配置文件
[frameCfg0]
Period = 5000
flag = 1
dlNum = 7
dlNums = 6
ulNum = 2
ulNums = 4
test_ini.c 测试实现的接口
//测试调用读取config.ini接口
#include<stdio.h>
#include "config.h"
int BSP_ConfigLoadAll(char * path);
void get_node(void);
int main(int argc, char *argv[])
{
int ret = 0;
char * path ;
if (argc < 2)
{
printf("Usage : test /home/cj");
return -1;
}
path = argv[1];
ret = BSP_ConfigLoadAll(path);
if (ret){
printf("ret:%d failed can't %s \n", ret, path);
}
get_node();
return 0;
}
makefile:
#exprot LD_LIBRARY_PATH=自己的配置文件路径
TARGET = libbspRru.so
CXX := g++
OBJS := config.o
CFLAGS = -std=c++11 -fno-pie -O2 -Wall -shared -fPIC
CC = gcc
.PHONY :all
all:$(TARGET)
$(TARGET): $(OBJS)
$(CXX) -shared -o $@ $^
%.o : %.cpp
$(CXX) -c $< $(CFLAGS)
.PHONY :clean
clean:
rm *.o *.so *.gch -f test
.PHONY:test
test:test_ini.o
$(CC) -o $@ $^ -lbspRru -L 包含自己的配置文件路径
编译测试:
make
make test
有告警是CFLAGS引起的,编译c文件的时候没有-std=c++11的选项 ,编译的时候默认选择CFLAGS宏,默认时这个是空的,我们赋值了,所以有告警,不影响,也可以修改先makefile去除;把-std=c++11放到 %.o : %.cpp的命令中去,懒得修改测试截图了;
测试执行前先执行:
exprot LD_LIBRARY_PATH=自己的配置文件路径 ## 很重要不然可能找不到动态库
这样就基本成功了。
————————————————
版权声明:本文为优快云博主「kidd_cj」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/c4679281314/article/details/122951274
C/C++ 操作ini文件(SinpleIni 跨平台库) (比较完整 ****)
最近在学习时,发现自己还不会操作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中,文件中是不会显示出乱码,但是读取写入时会有乱码!
(即文件名乱码,文件名在 linux中为 unicode。但是,在 win OS中,可能是 unicode,也可能是本地编码。)
我遇到的乱码问题,通过上面的方法就可以解决了!
四、封装
可以根据自己项目的具体需求去封装成方便调用的接口去使用!
例如我下面的用法:
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 §ion);
// 添加一个新的key和value,value可以默认为空
bool addValue(const std::string §ion, const std::string &key, const std::string &value = "");
bool addLongValue(const std::string §ion, const std::string &key, const long value = 0);
bool addDoubleValue(const std::string §ion, const std::string &key, const double value = 0.0);
bool addBoolValue(const std::string §ion, const std::string &key, const bool value = false);
// 修改value,如果key不存在,则会创建key和value
bool setValue(const std::string §ion, const std::string &key, const std::string &value);
bool setLongValue(const std::string §ion, const std::string &key, const long value = 0);
bool setDoubleValue(const std::string §ion, const std::string &key, const double value = 0.0);
bool setBoolValue(const std::string §ion, const std::string &key, const bool value = false);
// 删除key
bool deleteKey(const std::string §ion, const std::string &key);
// 删除key,如果最后一个key也被删除了,那么section也会被一起删除掉
bool deleteKeys(const std::string §ion, const std::string &key, const bool deleteSectionIfEmpty = true);
// 删除section,整个section和其中的所有键值
bool deleteSection(const std::string §ion);
// 获取string类型值
std::string getValue(const std::string §ion, const std::string &key, const std::string &defualtValue = "");
// 获取char类型值
char getValueC(const std::string §ion, const std::string &key, const char &defualtValue = '\0');
// 获取long、int、short类型
long getLongValue(const std::string §ion, const std::string &key, const short &defualtValue = -1);
// 获取double、float类型
double getDoubleValue(const std::string §ion, const std::string &key, const double &defualtValue = 0.0);
// 获取bool类型
bool getBoolValue(const std::string §ion, const std::string &key, const bool &defualtValue = false);
// 获取section里有多少值
int getSectionSize(const std::string §ion);
// 遍历所有
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去初始化了!
————————————————
版权声明:本文为优快云博主「cpp_learners」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/cpp_learner/article/details/128780799
simpleini 官方手册 (***)
https://github.com/brofield/simpleini
README.md
simpleini
A cross-platform library that provides a simple API to read and write INI-style configuration files. It supports data files in ASCII, MBCS and Unicode. It is designed explicitly to be portable to any platform and has been tested on Windows, WinCE and Linux. Released as open-source and free using the MIT licence.
ConvertUTF.h : ensure that UTF32 is 32-bits on a 64-bit platform. It should still be 32 on a 32-bit platform even with this change.
Feature Summary
- MIT Licence allows free use in all software (including GPL and commercial)
- multi-platform (Windows 95 to Windows 10, Windows CE, Linux, Unix)
- loading and saving of INI-style configuration files
- configuration files can have any newline format on all platforms
- liberal acceptance of file format
- key/values with no section, keys with no value
- removal of whitespace around sections, keys and values
- support for multi-line values (values with embedded newline characters)
- optional support for multiple keys with the same name
- optional case-insensitive sections and keys (for ASCII characters only)
- saves files with sections and keys in the same order as they were loaded
- preserves comments on the file, section and keys where possible
- supports both char or wchar_t programming interfaces
- supports both MBCS (system locale) and UTF-8 file encodings
- system locale does not need to be UTF-8 on Linux/Unix to load UTF-8 file
- support for non-ASCII characters in section, keys, values and comments
- support for non-standard character types or file encodings via user-written converter classes
- support for adding/modifying values programmatically
- should compile with no warnings in most compilers
Documentation
Full documentation of the interface is available in doxygen format.
Examples
These snippets are included with the distribution in the automatic tests as ts-snippets.cpp.
SIMPLE USAGE / 简明用法
// simple demonstration
CSimpleIniA ini;
//如果不指定,则可能是:utf8 /16/ 32 ,是这样吗 ?
ini.SetUnicode(); // SetUnicode(true); void setUnicode(const bool utf8 = true);
//打开文件
SI_Error rc = ini.LoadFile("example.ini");
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_OK);
//读值
const char* pv;
pv = ini.GetValue("section", "key", "default");
ASSERT_STREQ(pv, "value");
//写
ini.SetValue("section", "key", "newvalue");
//读值:如果“值”无效,则返回默认值:default
pv = ini.GetValue("section", "key", "default");
ASSERT_STREQ(pv, "newvalue");
LOADING DATA
// load from a data file CSimpleIniA ini; SI_Error rc = ini.LoadFile("example.ini"); if (rc < 0) { /* handle error */ }; ASSERT_EQ(rc, SI_OK); // load from a string const std::string example = "[section]\nkey = value\n"; CSimpleIniA ini; SI_Error rc = ini.LoadData(example); if (rc < 0) { /* handle error */ }; ASSERT_EQ(rc, SI_OK);
GETTING SECTIONS AND KEYS
// get all sections CSimpleIniA::TNamesDepend sections; ini.GetAllSections(sections); // get all keys in a section CSimpleIniA::TNamesDepend keys; ini.GetAllKeys("section1", keys);
GETTING VALUES
// get the value of a key that doesn't exist
const char* pv;
pv = ini.GetValue("section1", "key99");
ASSERT_EQ(pv, nullptr);
// get the value of a key that does exist
pv = ini.GetValue("section1", "key1");
ASSERT_STREQ(pv, "value1");
// get the value of a key which may have multiple
// values. If hasMultiple is true, then there are
// multiple values and just one value has been returned
bool hasMulti;
pv = ini.GetValue("section1", "key1", nullptr, &hasMulti);
ASSERT_STREQ(pv, "value1");
ASSERT_EQ(hasMulti, false);
pv = ini.GetValue("section1", "key2", nullptr, &hasMulti);
ASSERT_STREQ(pv, "value2.1");
ASSERT_EQ(hasMulti, true);
// get all values of a key with multiple values
CSimpleIniA::TNamesDepend values;
ini.GetAllValues("section1", "key2", values);
// sort the values into a known order, in this case we want
// the original load order
values.sort(CSimpleIniA::Entry::LoadOrder());
// output all of the items
CSimpleIniA::TNamesDepend::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) {
printf("value = '%s'\n", it->pItem);
}
MODIFYING DATA
// add a new section rc = ini.SetValue("section1", nullptr, nullptr); if (rc < 0) { /* handle error */ }; ASSERT_EQ(rc, SI_INSERTED); // not an error to add one that already exists rc = ini.SetValue("section1", nullptr, nullptr); if (rc < 0) { /* handle error */ }; ASSERT_EQ(rc, SI_UPDATED); // get the value of a key that doesn't exist const char* pv; pv = ini.GetValue("section2", "key1", "default-value"); ASSERT_STREQ(pv, "default-value"); // adding a key (the section will be added if needed) rc = ini.SetValue("section2", "key1", "value1"); if (rc < 0) { /* handle error */ }; ASSERT_EQ(rc, SI_INSERTED); // ensure it is set to expected value pv = ini.GetValue("section2", "key1", nullptr); ASSERT_STREQ(pv, "value1"); // change the value of a key rc = ini.SetValue("section2", "key1", "value2"); if (rc < 0) { /* handle error */ }; ASSERT_EQ(rc, SI_UPDATED); // ensure it is set to expected value pv = ini.GetValue("section2", "key1", nullptr); ASSERT_STREQ(pv, "value2");
DELETING DATA
// deleting a key from a section. Optionally the entire // section may be deleted if it is now empty. bool done, deleteSectionIfEmpty = true; done = ini.Delete("section1", "key1", deleteSectionIfEmpty); ASSERT_EQ(done, true); done = ini.Delete("section1", "key1"); ASSERT_EQ(done, false); // deleting an entire section and all keys in it done = ini.Delete("section2", nullptr); ASSERT_EQ(done, true); done = ini.Delete("section2", nullptr); ASSERT_EQ(done, false);
SAVING DATA
// save the data to a string
std::string data;
rc = ini.Save(data);
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_OK);
// save the data back to the file
rc = ini.SaveFile("example2.ini");
if (rc < 0) { /* handle error */ };
ASSERT_EQ(rc, SI_OK);