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

相关推荐
Tony11542 小时前
UOS系统和windows系统wps文档显示差异问题解决
windows·wps·uos
达子6665 小时前
笔记-使用ffmpeg产生rtsp视频流,然后用进行VLC播放
windows·笔记·ffmpeg
没有名字的鬼5 小时前
C_字符数组存储汉字字符串及其索引
c语言·开发语言·数据结构
Goldinger5 小时前
vscode 配置c/c++环境 中文乱码
c语言·c++·vscode
nSponge6 小时前
【Duilib】 List控件支持多选和获取选择的多条数据
c++·windows·工具
skywalk81636 小时前
C语言基本知识复习浓缩版:标识符、函数、进制、数据类型
c语言·开发语言
Y Shy6 小时前
Windows C++开发环境:VSCode + cmake + ninja + msvc (cl.exe) + msys2/bash shell
c++·windows·vscode·msvc·cmake·msys2·ninja
yngsqq8 小时前
寻找最短路径
运维·服务器·windows
graceyun8 小时前
牛客网刷题 ——C语言初阶(6指针)——BC105 矩阵相等判定
c语言
daopuyun8 小时前
C/C++编程安全标准GJB-8114解读——名称、符号与变量使用类
java·c语言·c++