C语言读取 ini 配置文件,修改/添加键值对

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); // 关闭文件
}

参考:

1、C语言读取写入 ini 配置文件_c读取ini配置文件-CSDN博客

相关推荐
三体世界14 分钟前
测试用例全解析:从入门到精通(1)
linux·c语言·c++·python·功能测试·测试用例·测试覆盖率
csdn_aspnet39 分钟前
Windows、Linux 系统 nodejs 和 npm 版本更新及错误修复
linux·windows·npm·node.js
程序员东岸43 分钟前
C语言入门指南:字符函数和字符串函数
c语言·笔记·学习·程序人生·算法
人工干智能8 小时前
科普:在Windows个人电脑上使用Docker的极简指南
windows·docker·容器
kyle~10 小时前
排序---插入排序(Insertion Sort)
c语言·数据结构·c++·算法·排序算法
张晓~1833994812111 小时前
短视频矩阵源码-视频剪辑+AI智能体开发接入技术分享
c语言·c++·人工智能·矩阵·c#·php·音视频
纵有疾風起12 小时前
数据结构中的排序秘籍:从基础到进阶的全面解析
c语言·数据结构·算法·排序算法
夜猫逐梦14 小时前
【Lua】Windows 下编写 C 扩展模块:VS 编译与 Lua 调用全流程
c语言·windows·lua
_OP_CHEN14 小时前
数据结构(C语言篇):(十三)堆的应用
c语言·数据结构·二叉树·学习笔记·堆排序··top-k问题
网硕互联的小客服14 小时前
Windows 2012 系统如何修改网卡DNS?
windows