利用sampleini库实现c/c++操作ini配置文件

github sampleini库下载链接: https://github.com/brofield/simpleini

 下载后只需一下三个文件即可:

配置文件格式:采用以下格式;

 

 1. 加载配置文件前重要设置

/*设置是否使用utf8编码作为加载/保存; 在ini数据被加载后不可设置; 默认true;*/
void SetUnicode(bool a_bIsUtf8 = true) {
    if (!m_pData) m_bStoreIsUtf8 = a_bIsUtf8;
};

/*是否允许使用多个相同的key;
  若为true; 则:
  [section]
  test = value1;
  test = value2;
  上面两个key相同,value不同可被允许设置;

  若为false;
  [section]
  test = value2; //value1 为上次值,被覆盖;
*/
void SetMultiKey(bool a_bAllowMultiKey = true) {
    m_bAllowMultiKey = a_bAllowMultiKey;
}

/*是否允许数据value跨越文件中的多行*/
void SetMultiLine(bool a_bAllowMultiLine = true) {
    m_bAllowMultiLine = a_bAllowMultiLine;
}

/*写入键/值时是否应该在等号周围添加空格;
  若为true; 则 key = value 等号两边有空格;
  若为false;则 key=value 等号两边无空格;
*/
void SetSpaces(bool a_bSpaces = true) {
    m_bSpaces = a_bSpaces;
}

/*是否应该识别或解析单行value中的引号;*/
void SetQuotes(bool a_bParseQuotes = true) {
    m_bParseQuotes = a_bParseQuotes;
}

//默认状态如下;
printf("IsUnicode = %d \n",conf.IsUnicode());//0
printf("IsMultiKey = %d \n",conf.IsMultiKey());//0
printf("IsMultiLine = %d \n",conf.IsMultiLine());//0
printf("UsingSpaces = %d \n",conf.UsingSpaces());//1
printf("UsingQuotes = %d \n",conf.UsingQuotes());//0

2. 加载数据

//参数为文件路径
SI_Error LoadFile(
    const char * a_pszFile
    );

(1) 该函数有很多同名函数(重载函数);

(2) 该函数加载是将配置文件从磁盘上加载到内存中; 接下来的很多操作如:setValue等仅仅是改变内存中的数据;在系统掉电是不会保存到磁盘上的; 在内存中操作的目的就是快;

(3) 要想将内存中改变的数据保存到磁盘,需要调用 saveFile()函数将内存中的数据保存到磁盘上;

3. 获取配置信息

/*获取所有[section]名字;
  返回的名字存储在a_names中;
  有定义: typedef std::list<Entry> TNamesDepend; 可知实际为list;
*/
void GetAllSections(
    TNamesDepend & a_names
    ) const;

/*检索所有[section]中的key和val键值对;*/
const TKeyVal * GetSection(
    const SI_CHAR * a_pSection
    ) const;

/*获取[section]中的所有key值,保存到 a_names中; */
bool GetAllKeys(
    const SI_CHAR * a_pSection,
    TNamesDepend &  a_names
    ) const;

/*根据section,key获取对应的value*/
 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;

 //根据section,key获取bool类型,double类型,long类型,
 bool GetBoolValue(
    const SI_CHAR * a_pSection,
    const SI_CHAR * a_pKey,
    bool            a_bDefault     = false,
    bool *          a_pHasMultiple = NULL
    ) const;
 double GetDoubleValue(
    const SI_CHAR * a_pSection,
    const SI_CHAR * a_pKey,
    double          a_nDefault     = 0,
    bool *          a_pHasMultiple = NULL
    ) const;
  bool GetBoolValue(
    const SI_CHAR * a_pSection,
    const SI_CHAR * a_pKey,
    bool            a_bDefault     = false,
    bool *          a_pHasMultiple = NULL
    ) const;

4. 修改(内存)内容

/*设置值
  参数1: section字符串
  参数2: key字符串
  参数3: value字符串
*/
SI_Error SetValue(
const SI_CHAR * a_pSection,
const SI_CHAR * a_pKey,
const SI_CHAR * a_pValue,
const SI_CHAR * a_pComment      = NULL,
bool            a_bForceReplace = false
)

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,
bool            a_bForceReplace = false
);

SI_Error SetDoubleValue(
const SI_CHAR * a_pSection,
const SI_CHAR * a_pKey,
double          a_nValue,
const SI_CHAR * a_pComment      = NULL,
bool            a_bForceReplace = false
);

SI_Error SetBoolValue(
const SI_CHAR * a_pSection,
const SI_CHAR * a_pKey,
bool            a_bValue,
const SI_CHAR * a_pComment      = NULL,
bool            a_bForceReplace = false
);

调用了上述设置key对应的值后并不能修改磁盘上的内容;原因是设置的内容是loadFile到内存中的数据;

需要使用 saveFile() 函数才能真正将内存中的数据保存到磁盘上;

//内部调用了继承了OutputWriter类的FileWriter类,并调用了write函数;
FILE *fp = fopen("./config.ini","w+");
conf.SaveFile(fp);
fclose(fp);

或者

//其内部也是将文件用fopen打开,然后调用saveFile(FILE *);
conf.SaveFile("./config.ini");

 5. 删除节点/键/值

//将会删掉[section]为"server"的节点;
conf.Delete("server", NULL);

//仅删掉[section]为type, key为"_int"的键和值;
conf.Delete("type", "_int");

//删除[section]为"type",key为"_long"的键和值;
conf.DeleteValue("type", "_long", NULL);	

//删除[section]为"type",key为"_bool"的键和值(不管值是否能够对应都会被删);
conf.DeleteValue("type", "_bool", "false");

 6. 测试示例

#include <iostream>
#include "SimpleIni.h"
#include <list>

using namespace std;

int main()
{
	SI_Error err;
	
	CSimpleIniA conf;
	
	conf.SetUnicode(true);//设置为utf8编码;

	//从磁盘加载到内存中;
	err = conf.LoadFile("./config.ini");
	if(SI_OK != err){
		cout << "load file err" << endl;
		return -1;
	}
	
	CSimpleIniA::TNamesDepend secNames;
	//获取所有section
	conf.GetAllSections(secNames);

	//遍历list
	for(const auto &iter : secNames){
		cout << "[section] = " << iter.pItem << endl;

		//通过section名字获取键值对;
		const CSimpleIniA::TKeyVal *pkeyVal = conf.GetSection(iter.pItem);
		if(nullptr != pkeyVal){
			for(const auto &iter : *pkeyVal){
				cout << iter.first.pItem << " = " << iter.second << endl;
			}
		}
	}

	CSimpleIniA::TNamesDepend keyNames;
	if(true == conf.GetAllKeys("message", keyNames)){ //发现对应的section名,返回true
		printf("\n");
		for(const auto &iter : keyNames){
			cout << "keyName = " << iter.pItem << endl;
		}
	}

	CSimpleIniA::TNamesDepend valNames;
	if(true == conf.GetAllValues("server", "ip", valNames)){
		printf("\n");
		for(const auto &iter : valNames){
			cout << "valName = " << iter.pItem << endl;
		}
	}

	const char *val =  conf.GetValue("server", "port");
	if(val)
		cout << "val = " << val << endl;


	printf("bool = %d \n",conf.GetBoolValue("type", "_bool"));
	printf("_int = %ld \n",conf.GetLongValue("type", "_int"));
	printf("_double = %lf \n",conf.GetDoubleValue("type", "_double"));
	printf("_long = %ld \n",conf.GetLongValue("type", "_long"));

	err = conf.SetValue("type", "_bool", "false");
	if(err == SI_UPDATED){

		printf("update bool ok \n");
	}
	
	conf.SetLongValue("type", "_int", 666);
	conf.SetDoubleValue("type", "_double", 20.222);

	conf.Delete("server", NULL);//将会删掉[section]为"server"的节点;
	conf.Delete("type", "_int");//删掉[section]为type, key为"_int"的键和值;

	conf.DeleteValue("type", "_long", NULL);	//删除[section]为"type",key为"_long"的键和值;
	conf.DeleteValue("type", "_bool", "false");//删除[section]为"type",key为"_bool"的键和值(不管值是否能够对应都会被删);

	//才能完成真正的写;
	#if 0 //ok
	
	FILE *fp = fopen("./config.ini","w+");
	conf.SaveFile(fp);
	fclose(fp);
	#else
	conf.SaveFile("./config.ini");//其内部也是将文件用fopen打开,然后调用saveFile(FILE *);
	#endif 
	
	return 0;
}

实现了ini配置文件的增删改查; 而且可动态增加配置; 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在C/C++编程中,判断INI文件中某个节中键值对是否全部取完毕可以通过以下步骤: 1. 打开INI文件:使用 fopen 函数打开INI文件,获取文件指针。 2. 定位到指定节:通过取每一行的内容,并判断该行是否是目标节的开始行(以'['开头)来定位到指定节。 3. 取键值对:在定位到目标节后,可以通过 fgets 函数逐行取节的内容,判断取的内容是否是键值对(包含'='字符),如果是,则进行处理。 4. 判断是否取完毕:判断条件可以有多种方式,例如可以在循环过程中使用计数器记录取的键值对数量,然后与目标节中的键值对总数进行对比,如果相等则表示取完毕。 5. 关闭INI文件:使用 fclose 函数关闭打开的INI文件。 以下是一个简单的示例代码: ```c #include <stdio.h> #include <string.h> int main() { FILE *file; char line[256]; int count = 0; int targetCount = 0; int isInTargetSection = 0; // 打开INI文件 file = fopen("config.ini", "r"); if (file == NULL) { printf("无法打开INI文件\n"); return -1; } // 定位到指定节 while (fgets(line, sizeof(line), file) != NULL) { if (line[0] == '[' && strstr(line, "[TargetSection]") != NULL) { isInTargetSection = 1; } if (isInTargetSection && strchr(line, '=') != NULL) { targetCount++; } // 判断是否取完毕 if (targetCount > 0 && count == targetCount) { break; // 取完毕 } } // 关闭INI文件 fclose(file); // 输出结果 printf("目标节中的键值对总数:%d\n", targetCount); printf("已取的键值对数量:%d\n", count); return 0; } ``` 注意:示例代码仅用于演示思路,请根据具体的需求和INI文件格式进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

天未及海宽

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

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

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

打赏作者

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

抵扣说明:

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

余额充值