读写ini配置文件(C++)
文章目录
- 1、为什么要使用ini或者其它(例如xml,json)配置文件?
- 2、ini文件基本介绍
- 3、ini配置文件的格式
- 4、C++读写ini配置文件
- 5、 代码示例
- 6、 配置文件的解析库
文章转载于:https://blog.csdn.net/weixin_44517656/article/details/109014236
1、为什么要使用ini或者其它(例如xml,json)配置文件?
-
如果我们程序没有任何配置文件时,这样的程序对外是全封闭的,一旦程序需要修改一些参数必须要修改程序代码本身并重新编译,这样很不好,所以要用配置文件,让程序发布后还能根据需要进行必要的配置;
配置文件有很多如INI配置文件,XML配置文件,还有就是可以使用系统注册表等
。注意:ini的后缀名也不一定是".ini"也可以是".cfg",“.conf ”或者是”.txt"。因为ini文件实质就是txt文本文件。 -
配置文件除了读取外还可以写入:例如用户设置了习惯模式,这样下次启动读取文件的时候也是该模式
-
kv文件,是ini执行后出现的文件
2、ini文件基本介绍
- .ini 文件是Initialization File的缩写,即初始化文件 [1] ,是windows的系统配置文件所采用的存储格式,统管windows的各项配置,一般用户就用windows提供的各项图形化管理界面就可实现相同的配置了。但在某些情况,还是要直接编辑.ini才方便,一般只有很熟悉windows才能去直接编辑。开始时用于WIN3X下面,WIN95用注册表代替,以及后面的内容表示一个节,相当于注册表中的键。
- 除了windows2003很多其他操作系统下面的应用软件也有.ini文件,用来配置应用软件以实现不同用户的要求。
一般不用直接编辑这些.ini文件,应用程序的图形界面即可操作以实现相同的功能
。它可以用来存放软件信息,注册表信息等。
3、ini配置文件的格式
1、INI文件由节、键、值组成。
节:[section]
参数(键=值)name=value
注解注解使用分号表示(;)在分号后面的文字,直到该行结尾都全部为注解。
1)对节进行说明:
- 所有的parameters都是以sections为单位结合在一起的。所有的section名称都是独占一行,并且sections名字都被方括号包围着([ and ])。在section声明后的所有parameters都是属于该section。对于一个section没有明显的结束标志符,一个section的开始就是上一个section的结束,或者是end of the file。Sections一般情况下不能被nested,当然特殊情况下也可以实现sections的嵌套。因为INI文件可能是项目中共用的,所以使用[Section Name]段名来区分不同用途的参数区。
2)对参数进行说明:
- INI所包含的最基本的“元素”就是parameter;每一个parameter都有一个name和一个value,name和value是由等号“=”隔开。name在等号的左边。
3)对注释内容进行说明:
- 在INI文件中注释语句是以分号 “;” 开始的(有些人定义类是由#注释,例如下面的RrConfig)。所有的所有的注释语句不管多长都是独占一行直到结束的,在分号和行结束符之间的所有内容都是被忽略的。
4、C++读写ini配置文件
在VC中涉及的函数有如下四种。
1)读取字符串
//头文件:windows.h
//返回字符串的实际大小,根据系统环境不同失败返回值不同(0或-1)
DWORD GetPrivateProfileString( LPCTSTR lpAppName, // INI文件中的一个字段名[节名]可以有很多个节名(配置文件的section名),这个字串不区分大小写;LPCTSTR lpKeyName, // lpAppName 下的一个键名,也就是里面具体的变量名(配置文件的key名),这个字串不区分大小写;LPCTSTR lpDefault, // 如果lpReturnedString为空,则把这个变量赋给lpReturnedString,一般设为空("");LPTSTR lpReturnedString, // 存放键值的指针变量,用于接收INI文件中键值(数据)的接收缓冲区DWORD nSize, // 前一个参数对象lpReturnedString的缓冲区大小LPCTSTR lpFileName // 完整的INI文件路径名
);
2)读取整型值
UINT GetPrivateProfileInt(LPCTSTR lpAppName, // INI文件中的一个字段名[节名]可以有很多个节名LPCTSTR lpKeyName, // lpAppName 下的一个键名,也就是里面具体的变量名INT nDefault, // 如果没有找到指定的数据返回,则把个变量值赋给返回值LPCTSTR lpFileName // INI文件的路径
);
3)写入字符串
BOOL WritePrivateProfileString(LPCTSTR lpAppName, // INI文件中的一个字段名[节名]可以有很多个节名LPCTSTR lpKeyName, // lpAppName 下的一个键名,也就是里面具体的变量名LPCTSTR lpString, // 键值,也就是数据LPCTSTR lpFileName // INI文件的路径
);
4)写入整数值(没有相关函数,可以通过WritePrivateProfileString进行参数转换来实现)
5、 代码示例
由于VC提供的函数部分功能比较少,一般解析配置文件都是调用库或者别人在项目中使用过的类,所以上面只是为了让大家了解ini的格式及相关参数的意义。下面的代码其实不需要看懂,只需要你会用即可。
ReConfig.h文件
#ifndef RR_CONFIG_H_
#define RR_CONFIG_H_
#include <string>
#include <map>
namespace rr
{class RrConfig{public:RrConfig(){}~RrConfig(){}bool ReadConfig(const std::string & filename);std::string ReadString(const char* section, const char* item, const char* default_value);int ReadInt(const char* section, const char* item, const int& default_value);float ReadFloat(const char* section, const char* item, const float& default_value);private:bool IsSpace(char c);bool IsCommentChar(char c);void Trim(std::string & str);bool AnalyseLine(const std::string & line, std::string& section, std::string & key, std::string & value);private://std::map<std::string, std::string> settings_;std::map<std::string, std::map<std::string, std::string> >settings_;};
}
#endif
ReConfig.cpp文件
#include "ReConfig.h"
#include <fstream>
#include <stdlib.h>namespace rr
{bool RrConfig::IsSpace(char c){if (' ' == c || '\t' == c)return true;return false;}bool RrConfig::IsCommentChar(char c){switch (c) {case '#':return true;default:return false;}}void RrConfig::Trim(std::string & str){if (str.empty()){return;}int i, start_pos, end_pos;for (i = 0; i < str.size(); ++i) {if (!IsSpace(str[i])) {break;}}if (i == str.size()){str = "";return;}start_pos = i;for (i = str.size() - 1; i >= 0; --i) {if (!IsSpace(str[i])) {break;}}end_pos = i;str = str.substr(start_pos, end_pos - start_pos + 1);}bool RrConfig::AnalyseLine(const std::string & line, std::string& section, std::string & key, std::string & value){if (line.empty())return false;int start_pos = 0, end_pos = line.size() - 1, pos, s_startpos, s_endpos;if ((pos = line.find("#")) != -1){if (0 == pos){return false;}end_pos = pos - 1;}if (((s_startpos = line.find("[")) != -1) && ((s_endpos = line.find("]"))) != -1){section = line.substr(s_startpos + 1, s_endpos - 1);return true;}std::string new_line = line.substr(start_pos, start_pos + 1 - end_pos);if ((pos = new_line.find('=')) == -1)return false;key = new_line.substr(0, pos);value = new_line.substr(pos + 1, end_pos + 1 - (pos + 1));Trim(key);if (key.empty()) {return false;}Trim(value);if ((pos = value.find("\r")) > 0){value.replace(pos, 1, "");}if ((pos = value.find("\n")) > 0){value.replace(pos, 1, "");}return true;}bool RrConfig::ReadConfig(const std::string & filename){settings_.clear();std::ifstream infile(filename.c_str());//构造默认调用open,所以可以不调用open//std::ifstream infile;//infile.open(filename.c_str());//bool ret = infile.is_open()if (!infile) {return false;}std::string line, key, value, section;std::map<std::string, std::string> k_v;std::map<std::string, std::map<std::string, std::string> >::iterator it;while (getline(infile, line)){if (AnalyseLine(line, section, key, value)){it = settings_.find(section);if (it != settings_.end()){k_v[key] = value;it->second = k_v;}else{k_v.clear();settings_.insert(std::make_pair(section, k_v));}}key.clear();value.clear();}infile.close();return true;}std::string RrConfig::ReadString(const char* section, const char* item, const char* default_value){std::string tmp_s(section);std::string tmp_i(item);std::string def(default_value);std::map<std::string, std::string> k_v;std::map<std::string, std::string>::iterator it_item;std::map<std::string, std::map<std::string, std::string> >::iterator it;it = settings_.find(tmp_s);if (it == settings_.end()){//printf("111");return def;}k_v = it->second;it_item = k_v.find(tmp_i);if (it_item == k_v.end()){//printf("222");return def;}return it_item->second;}int RrConfig::ReadInt(const char* section, const char* item, const int& default_value){std::string tmp_s(section);std::string tmp_i(item);std::map<std::string, std::string> k_v;std::map<std::string, std::string>::iterator it_item;std::map<std::string, std::map<std::string, std::string> >::iterator it;it = settings_.find(tmp_s);if (it == settings_.end()){return default_value;}k_v = it->second;it_item = k_v.find(tmp_i);if (it_item == k_v.end()){return default_value;}return atoi(it_item->second.c_str());}float RrConfig::ReadFloat(const char* section, const char* item, const float& default_value){std::string tmp_s(section);std::string tmp_i(item);std::map<std::string, std::string> k_v;std::map<std::string, std::string>::iterator it_item;std::map<std::string, std::map<std::string, std::string> >::iterator it;it = settings_.find(tmp_s);if (it == settings_.end()){return default_value;}k_v = it->second;it_item = k_v.find(tmp_i);if (it_item == k_v.end()){return default_value;}return atof(it_item->second.c_str());}
}
main.cpp文件
#include <iostream>
#include "ReConfig.h"
#include <fstream>
#include <cassert>int main() {rr::RrConfig config;bool ret = config.ReadConfig("config.ini");if (ret == false) {printf("ReadConfig is Error,Cfg=%s", "config.ini");return 1;}std::string HostName = config.ReadString("MYSQL", "HostName", "");int Port = config.ReadInt("MYSQL", "Port", 0);std::string UserName = config.ReadString("MYSQL", "UserName", "");std::cout << "HostName=" << HostName << std::endl;std::cout << "Port=" << Port << std::endl;std::cout << "UserName=" << UserName << std::endl;return 0;
}
config.ini文件
[MYSQL]
HostName=127.0.0.1
Port=3306
UserName=root
文件路径以及编译结果如图所示:
6、 配置文件的解析库
1)libconfig, C++版本是libconfig++
http://blog.csdn.net/crazyhacking/article/details/9668981
2)C++的Json解析库:jsoncpp和boost .
http://www.cnblogs.com/lidabo/archive/2012/10/31/2748026.html
相关文章:

读写ini配置文件(C++)
文章目录 1、为什么要使用ini或者其它(例如xml,json)配置文件?2、ini文件基本介绍3、ini配置文件的格式4、C读写ini配置文件5、 代码示例6、 配置文件的解析库 文章转载于:https://blog.csdn.net/weixin_44517656/article/details/109014236 1、为什么要…...
Python对接亚马逊电商平台SP-API的一些概念理解准备
❝ 除了第三方服务商,其实亚马逊卖家本身也可以通过和SP-API的对接,利用程序来自动化亚马逊店铺销售运营管理中很多环节的工作,简单的应用比如可以利用SP-API的对接,实现亚马逊卖家后台各类报表的定期自动下载以及数据分析整理工…...

[Halcon3D] 主流的3D光学视觉方案及原理
📢博客主页:https://loewen.blog.csdn.net📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢本文由 丶布布原创,首发于 CSDN,转载注明出处🙉📢现…...

Go Web下gin框架使用(二)
〇、gin 路由 Gin是一个用于构建Web应用程序的Go语言框架,它具有简单、快速、灵活的特点。在Gin中,可以使用路由来定义URL和处理程序之间的映射关系。 r : gin.Default()// 访问 /index 这个路由// 获取信息r.GET("/index", func(c *gin.Con…...

算法笔记-线段树合并
线段树合并 前置知识:权值线段树、动态开点 将两棵线段树的信息合并成一棵线段树。 可以新建一颗线段树保存原来两颗线段树的信息,也可以将第二棵线段树维护的信息加到第一棵线段树上。 前者的空间复杂度较高,如果合并之前的线段树不会再用…...

Fiddler抓取IOS数据包实践教程
Fiddler是一个http协议调试代理工具,它能够记录并检查所有你的电脑和互联网之间的http通讯,设置断点,查看所有的“进出”Fiddler的数据(指cookie,html,js,css等文件)。 本章教程,主要介绍如何利用Fiddler抓取IOS数据包相关教程。 目录 一、打开Fiddler监听端口 二、配置网…...

Ansible基础4——变量、机密、事实
文章目录 一、变量二、机密2.1 创建加密文件2.2 查看加密文件2.3 编辑加密文件内容2.4 加密现有文件2.5 解密文件2.6 更改加密密码 三、事实3.1 收集展示事实3.2 展示某个结果3.3 新旧事实命令3.4 关闭事实3.5 魔法变量 一、变量 常设置的变量: 要创建的用户要安装的…...

React实现Vue的watch监听属性
在 Vue 中可以简单地使用 watch 来监听数据的变化,还能获取到改变前的旧值,而在 React 中是没有 watch 的。 React中比较复杂,但是我们如果想在 React 中实现一个类似 Vue 的 watch 监听属性,也不是没有办法。 在React类组件中实…...

axios、跨域与JSONP、防抖和节流
文章目录 一、axios1、什么是axios2、axios发起GET请求3、axios发起POST请求4、直接使用axios发起请求 二、跨域与JSONP1、了解同源策略和跨域2、JSONP(1)实现一个简单的JSONP(2)JSONP的缺点(3)jQuery中的J…...

macOS Ventura 13.5beta2 (22G5038d)发布
系统介绍 黑果魏叔 6 月 1 日消息,苹果今日向 Mac 电脑用户推送了 macOS 13.5 开发者预览版 Beta 2 更新(内部版本号:22G5038d),本次更新距离上次发布隔了 12 天。 macOS Ventura 带来了台前调度、连续互通相机、Fac…...

jwt----介绍,原理
token:服务的生成的加密字符串,如果存在客户端浏览器上,就叫cookie -三部分:头,荷载,签名 -签发:登录成功,签发 -认证:认证类中认证 # jwt&…...

Three.js--》实现3d水晶小熊模型搭建
目录 项目搭建 初始化three.js基础代码 加载背景纹理 加载小熊模型 今天简单实现一个three.js的小Demo,加强自己对three知识的掌握与学习,只有在项目中才能灵活将所学知识运用起来,话不多说直接开始。 项目搭建 本案例还是借助框架书写…...

《阿里大数据之路》研读笔记(1)
首先先看到OLAP和OLTP的区别: OLTP(Online transaction processing):在线/联机事务处理。典型的OLTP类操作都比较简单,主要是对数据库中的数据进行增删改查,操作主体一般是产品的用户或者是操作人员。 OLAP(Online analytical processing):…...

Logback 日志框架详解
一、Logback 简介 Logback 是一个日志框架,旨在成为 log4j 的替代品。它由 Ceki Glc 创建并维护,是一款开源的日志框架,是 slf4j(Simple Logging Facade for Java)的实现。相比于 log4j,Logback 具有更高的…...

BIO、NIO、AIO 有什么区别?
BIO (Blocking I/O): Block IO 同步阻塞式 IO ,传统 IO,特点是模式简单、使用方便,并发处理能力低。 同步阻塞 I/O 模式,数据的读取写入必须阻塞在一个线程内等待其完成,在活动连接数不是特别高(…...

nginx和tomcat负载均衡、静态分离
tomcat重要目录 bin 存放启动和关闭Tomcat脚本conf存放Tomcat不同的配置文件doc存放Tomcat文档lib存放Tomcat运行需要的库文件logs存放Tomcat执行时的log文件src存放Tomcat的源代码webappsTomcat的主要Web发布目录work存放jsp编译后产生的class文件 nginx负载均衡原理 nginx实…...

用AI写出的高考作文!
今天是6月7日,又到了每一年高考的日子。小灰自己参加高考是在2004年,距离现在已经将近20年,现在回想起来,真的是恍如隔世。 今天高考语文的作文题是什么呢? 全国甲卷的题目是:人技术时间 人们因技术发展得以…...

chatgpt赋能python:Python屏幕输入介绍:了解命令行输入的基本知识
Python屏幕输入介绍:了解命令行输入的基本知识 Python是一种使用广泛的编程语言,用于编写各种类型的应用程序,包括图形用户界面应用程序和基于命令行的应用程序。对于基于命令行的应用程序来说,屏幕输入非常重要。本文将介绍Pyth…...

bert中文文本摘要代码(1)
bert中文文本摘要代码 写在最前面关于BERT使用transformers库进行微调 load_data.py自定义参数collate_fn函数BertDataset类主函数 tokenizer.py创建词汇表encode函数decode函数 写在最前面 熟悉bert+文本摘要的下游任务微调的代码,方便后续增加组件实现…...

为何溃坝事故频发,大坝安全如何保障?
随着水利水电工程的重要性日益突显,水库大坝安全越来越受到相关部门的重视。因为大坝的安全直接影响水利工程的功能与作用,因此对大坝安全的监测显得十分必要。大坝安全监测的作用是能够及时掌握大坝的运行状态,及时发现大坝的变形、渗漏等异…...

第十九章_手写Redis分布式锁
锁的种类 单机版同一个JVM虚拟机内synchronized或者Lock接口。 分布式多个不同JVM虚拟机,单机的线程锁机制不再起作用,资源类在不同的服务器之间共享了。 一个靠谱分布式锁需要具备的条件和刚需 独占性 :OnlyOne,任何时刻只能有且…...

电路设计【8】原理图中VCC、VDD、VEE、VSS、VBAT各表示什么意思
文章目录 一、名词解析二、应用讲解三、举例分析:为什么stm32vet6中要分出5对VDD VSS?它们分别负责哪些模块的供电? 一、名词解析 (1)VCC:Ccircuit 表示电路的意思, 即接入电路的电压 (2&…...

Volatile、Synchronized、ReentrantLock锁机制使用说明
一、Volatile底层原理 volatile是轻量级的同步机制,volatile保证变量对所有线程的可见性,不保证原子性。 当对volatile变量进行写操作的时候,JVM会向处理器发送一条LOCK前缀的指令,将该变量所在缓存行的数据写回系统内存。由于缓…...

港联证券|AI概念股继续活跃 科创50指数逆势走高
周三,A股市场出现极致分化态势。得益于存储芯片为代表的硬科技股的强势,科创50指数逆势走高。但创业板指、深证成指等主要股指仍然跌跌不休,沪指险守3200点关口。AI概念股继续逆势活跃,国资云、数据方向领涨,算力概念股…...

分布式事务一 事物以及分布式事物介绍
一 事务简介 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中,一个事务由一组SQL语句组成。事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。 原子性(at…...

【十四】设计模式~~~行为型模式~~~中介者模式(Java)
【学习难度:★★★☆☆,使用频率:★★★★★】 3.1. 模式动机 建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在此,发生改变的对象称为观察目标&#…...

css3--nth-child的用法
目录 使用CSS nth-child选择器基本用法使用公式从零开始关键点结论 使用CSS nth-child选择器 CSS的 :nth-child 选择器是一个强大的工具,允许我们根据它们在父元素中的位置选择元素。这为我们提供了更大的灵活性来控制页面上的元素。 基本用法 基本形式为 :nth-c…...

【假捻发加工生产工单下达】
假捻工单是需要下到工作中心的,比如A01机台或者A02机台。 所以下工单之前要先查询A01机台上的最新工单量。 查询结果如下: 她会按照创建时间进行排序,后下的工单排在最前面 (如果下了个新工单,那么前一个工单的执行状态会自动改为关闭。) 因此查询结果,最上面的工单执…...

Go for-range VS for
Go 语言中,for-range 可以用来遍历string、数组(array)、切片(slice)、map和channel,实际使用过程踩了一些坑,所以,还是总结记录下for-range的原理。 首先,go是值传递语言。变量是指针类型,复制指针传递&a…...

大数据教程【01.01】--大数据介绍及开发环境
更多信息请关注WX搜索GZH:XiaoBaiGPT 大数据简介 大数据(Big Data)是指规模庞大、结构复杂、增长速度快且难以使用传统技术处理的数据集合。大数据分析可以帮助企业和组织从海量的数据中提取有价值的信息,用于业务决策、市场分析、…...