安徽网站建设首选-晨飞网络,网站建设项目可行性报告,html网页设计代码作业正能量,wordpress 入门教程最近在学习时#xff0c;发现自己还不会操作ini文件#xff0c;想着以前工作时接触到的项目或多或少都要用到ini文件去保存初始化程序的数据#xff1b;所以赶紧去网上搜索以下C/C操作ini文件都有些什么库可以玩玩#xff1b;搜索到有#xff1a;
1. inih#xff1a;这是…最近在学习时发现自己还不会操作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 所对应的多个 valueini.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 stringtypedef struct st_env_config {// 对应ini文件// sectionint _int;long _long;double _double;float _float;bool _bool;std::string _string;char _char;// serverstd::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.hclass 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();// 添加一个新的sectionbool addSection(const std::string section);// 添加一个新的key和valuevalue可以默认为空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和valuebool 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);// 删除keybool 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 iostreamIniconfig::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;// 删除 keydone _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 和 valuefor (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去初始化了