C语言读取 ini 配置文件,修改/添加键值对
C语言读取 ini 配置文件,对section中的键值对进行修改/添加,如果section不存在,则在末尾将新的section/key/value 添加进去。
一、了解什么是INI文件?
ini 文件是Initialization File的缩写,即初始化文件,这是用来配置应用软件以实现不同用户的要求。
二、INI文件的格式
INI文件由节、键、值组成。
一个简单的的INI文件例子如下:
/*test.ini*/
[city]
beijing = hello-beijing
shanghai = hello-shanghai
#information
[study]
highschool = huafuyi
university = guofangkeda
[xinming]
name = lilei
如上例子,[city]就是节,=号左边的值是键,=号右边的是值。
读取key对应的value值
cpp
/*
* 功能: 读取key对应的value值
* 入口参数: filename
* 要读取的文件路径
* title
* 配置文件中一组数据的标识
* key
* 这组数据中要读出的值的标识
* 返回值: 找到需要查的值则返回正确结果 0
* 否则返回-1
*/
int GetIniKeyString(char* filename, char* title, char* key, char* buf)
{
FILE* fp;
int flag = 0;
char sTitle[64], * wTmp;
char sLine[1024];
// 节section字符串
sprintf(sTitle, "[%s]", title);
if (NULL == (fp = fopen(filename, "r")))
{
printf("open %s failed.\n", filename);
perror("fopen failed.\n");
return -1;
}
// 读取ini中的每一行
while (NULL != fgets(sLine, 1024, fp))
{
// 处理ini文件中的注释行
if (0 == strncmp("//", sLine, 2))
continue;
if (('#' == sLine[0]) || ';' == sLine[0])
continue;
// 定位=的位置
wTmp = strchr(sLine, '=');
if ((NULL != wTmp) && (1 == flag))
{
if (0 == strncmp(key, sLine, strlen(key)))
{ // 长度依文件读取的为准
sLine[strlen(sLine) - 1] = '\0';
fclose(fp);
while (*(wTmp + 1) == ' ')
{
wTmp++;
}
// 获取key对应的value
strcpy(buf, wTmp + 1);
return 0;
}
}
else
{
if (0 == strncmp(sTitle, sLine, strlen(sTitle)))
{ // 长度依文件读取的为准
// 不存在键值对的情况下,标记flag
flag = 1; // 找到标题位置
}
}
}
fclose(fp);
return -1;
}
修改/添加key-value键值对
cpp
/*OK--查找section中是否存在key,存在则将key对应的值修改为val,不存在则将key对应的val添加在section后面。*/
int PutIniKeyString2(char* filename, char* title, char* key, char* val)
{
FILE* fpr, * fpw;
int flag = 0;
int rtn = 0;
char sLine[1024], sTitle[32], * wTmp;
sprintf(sTitle, "[%s]", title);
if (NULL == (fpr = fopen(filename, "r")))
{
printf("读取原文件失败.\n");
return -1;// 读取原文件
}
// 临时文件名
sprintf(sLine, "%s.tmp", filename);
if (NULL == (fpw = fopen(sLine, "w")))
{
printf("写入失败.\n");
return -1;// 写入临时文件
}
while (NULL != fgets(sLine, 1024, fpr))
{
if (2 != flag)
{ // 如果找到要修改的那一行,则不会执行内部的操作
wTmp = strchr(sLine, '=');
if ((1 == flag))
{
// 找到对应的key
if ((NULL != wTmp) && (0 == strncmp(key, sLine, strlen(key))))
{ // 长度依文件读取的为准
flag = 2;// 更改值,方便写入文件
sprintf(wTmp + 1, " %s\n", val);
}
else
{
if ((sLine[0] == '\n'))
{
/* 没有找到对应的key,则在section末尾添加新的key/value */
//fseek(fpw, 0, SEEK_END);-((long)strlen(sLine))
fseek(fpw, 0, SEEK_CUR);
fprintf(fpw, "%s = %s\n", key, val);
flag = 0;
}
}
}
else
{
// 找到section的位置
if (0 == strncmp(sTitle, sLine, strlen(sTitle)))
{ // 长度依文件读取的为准
flag = 1; // 找到标题位置
}
}
}
fputs(sLine, fpw); // 写入临时文件
}
if (-1 == flag)
{ /* 没有找到对应的section,则在文件末尾添加新的section/key/value */
fseek(fpw, 0, SEEK_END);
fprintf(fpw, "%s\n", sTitle);
fprintf(fpw, "%s = %s\n\n", key, val);
}
fclose(fpr);
fclose(fpw);
sprintf(sLine, "%s.tmp", filename);
rtn = rename(sLine, filename);// 将临时文件更新到原文件
if (rtn != 0)
{
if (errno == EEXIST)
{
// 如果目标文件已经存在,需要先删除,再重命名
if (remove(filename) == 0)
{
if (rename(sLine, filename) == 0)
{
return 0;
}
else
{
return -1;
}
}
}
}
return rtn;
}
测试程序
头文件 ini.h
cpp
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
constexpr auto BUF_SIZE = 256;
int GetIniKeyString(char* filename, char* title, char* key, char* buf);
int PutIniKeyString2(char* filename, char* title, char* key, char* val);
主函数 main.c
cpp
#include "ini.h"
int main(int argc, char const* argv[])
{
int ret;
char buff[100];
//readSpeed();
//readExcel();
int xishu_gain = 2 << 25;//滤波器系数放大倍数.
*******************OK**************************
char filename[] = "./test.ini";
char title[] = "city";
char key[] = "beijing";
ret = GetIniKeyString(filename, title, key, buff);//读取ini文件key对应的vlaue
printf("ret:%d,%s\n", ret, buff);
char filename[] = "./test.ini";
//char title2[] = "study";
//char key2[] = "highschool";
//ret = GetIniKeyString(filename, title2, key2, buff);//读取ini文件key对应的vlaue
//printf("ret:%d,%s\n", ret, buff);
char title3[] = "xinming";
char key3[] = "name2";
char value3[] = "xiao-hua";
ret = PutIniKeyString2(filename, title3, key3, value3);//修改ini文件key对应的vlaue
printf("put ret:%d,%s\n", ret, value3);
//ret = GetIniKeyString(filename, title3, key3, buff);
//printf("ret:%d,%s\n", ret, buff);
//****************OK*****************************
return 0;
}
测试结果ini文件:
cpp
/*test.ini*/
[city]
beijing = hello-beijing
shanghai = hello-shanghai
wuhan = hello-wuhan
wuhan1 = hello-wu-han
wuhan2 = hello-wuhan
#information
[study]
highschool = huafuyi
university = guofangkeda
xiaoxue = huafucunxiao
xiaoxue1 = huafu-cunxiao1
[xinming]
name = lilei
name1 = xiao-ming1
name2 = xiao-hua
cpp
/*test.ini*/
[city]
beijing = hello-beijing
shanghai = hello-shanghai
wuhan = hello-wuhan
wuhan1 = hello-wu-han
wuhan2 = hello-wuhan
#information
[study]
highschool = huafuyi
university = guofangkeda
xiaoxue = huafucunxiao
xiaoxue1 = huafu-cunxiao1
[xinming]
name = lilei
name1 = xiao-ming1
name2 = xiao-hua
[tizhi]
weight = 80kg
weight1 = 80kg
打开或创建名为"config.ini"的文件
cpp
{
FILE* file = fopen("config.ini", "w");//打开或创建名为"config.ini"的文件
if (file == NULL)
{
printf("无法创建文件\n");
return -1;
}
// 写入配置项到文件
fprintf(file, "[Section]\n");
fprintf(file, "key=value\n");
fprintf(file, "\n[Another Section]\n");
fprintf(file, "another_key=another_value\n");
fclose(file); // 关闭文件
}
参考: