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博客

相关推荐
代码雕刻家19 分钟前
数据结构-3.9.栈在递归中的应用
c语言·数据结构·算法
yufei-coder1 小时前
掌握 C# 中的 LINQ(语言集成查询)
windows·vscode·c#·visual studio
Kalika0-02 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
代码雕刻家2 小时前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构
龙图:会赢的2 小时前
[C语言]--编译和链接
c语言·开发语言
Cons.W4 小时前
Codeforces Round 975 (Div. 1) C. Tree Pruning
c语言·开发语言·剪枝
挥剑决浮云 -4 小时前
Linux 之 安装软件、GCC编译器、Linux 操作系统基础
linux·服务器·c语言·c++·经验分享·笔记
立秋67894 小时前
Python的defaultdict详解
服务器·windows·python
Indigo_code5 小时前
【数据结构】【链表代码】合并有序链表
数据结构·windows·链表