Linux下配置文件读取操作流程及其C代码实现

一、概述
Linux具有免费、可靠、安全、稳定、多平台等特点,因此深受广大程序员的欢迎。
为了体现软件产品的灵活性,可添加配置文件存放某些重要的参数,在部署的时候根据实际的安装环境对每个配置项的值进行设置。这就要求程序能够准确读取到各个配置项的值。
本文详细介绍了Linux下配置文件的读取方法及读取操作的C代码实现,为相关的软件开发工作的开展提供了有益的参考。

二、配置文件介绍
为了便于程序处理,对配置文件的命名及内容格式有一些约定,具体如下:
第一,配置文件的后缀为ini,如本文中使用到的配置文件为:Config.ini。
第二,配置文件的内容由段名、注释和配置项组成,其中,段名由[]括起来,注释的内容以分号(;)开头,配置项采用等号(=)进行赋值。
本文使用的配置文件“Config.ini”包含的具体内容如下:

[EMPLOYEEINFO]
;the name of employee
EmployeeName=wang
;the age of employee
EmployeeAge=25

[EMPLOYERINFO]
;the name of employer
EmployerName=zhou
;the age of employer
EmployerAge=38

三、配置文件读取操作总体流程
实现配置文件读取操作的程序流程如图1所示。

图1 配置文件读取操作程序流程

四、配置文件读取操作重要流程
1.获取配置文件的全路径
在本文中,配置文件存放的全路径为:/home/zhou/zhouzx/GetConfig/ Config.ini。实现获取配置文件的全路径的程序函数为GetCompletePath(具体代码见后)。
说明:
(1) 函数getenv用来获取某参数的环境变量的内容。getenv(“HOME”)用于获取程序所在的当前用户的全路径。例如,本程序放在了zhou用户下,那么getenv(“HOME”)的值就为“/home/zhou”。
(2) Linux下目录之间的分隔符为“/”,这个与Windows下的分隔符有区别。

2.匹配段名和配置项名,并获取配置项的值
程序首先找到段名,然后在该段之下去匹配配置项名,最后获取配置项的值。
程序流程如图2所示。

图2 获取配置项值的程序流程

实现该功能的程序函数为GetStringContentValue(具体代码见后)。

五、对配置文件读取操作的测试
为了对编写的配置文件读取操作程序进行测试,定义了员工信息结构体和雇主信息结构体,分别用于存放从配置文件中读取到的员工信息和雇主信息。在main函数中将获取到的信息打印出来,以此来检查程序操作的正确性。

六、C程序实现
本程序命名为“GetConfig.c”,具体代码如下:

/**********************************************************************
* 版权所有 (C)2015, Zhou Zhaoxiong。
*
* 文件名称:GetConfig.c
* 文件标识:无
* 内容摘要:演示Linux下配置文件的读取方法
* 其它说明:无
* 当前版本:V1.0
* 作    者:Zhou Zhaoxiong
* 完成日期:20150507
*
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 数据类型重定义
typedef unsigned char   UINT8;
typedef signed   int    INT32;
typedef unsigned int    UINT32;

// 员工信息结构体定义
typedef struct
{
    UINT8  szEmployeeName[128];    // 员工姓名
    INT32  iEmployeeAge;           // 员工年龄
} T_EmployeeInfo;

// 雇主信息结构体定义
typedef struct
{
    UINT8  szEmployerName[128];    // 雇主姓名
    INT32  iEmployerAge;           // 雇主年龄
} T_EmployerInfo;

// 函数声明
void GetCompletePath(UINT8 *pszConfigFileName, UINT8 *pszWholePath);
void GetStringContentValue(FILE *fp, UINT8 *pszSectionName, UINT8 *pszKeyName, UINT8 *pszOutput, UINT32 iOutputLen);
void GetConfigFileStringValue(UINT8 *pszSectionName, UINT8 *pszKeyName, UINT8 *pDefaultVal, UINT8 *pszOutput, UINT32 iOutputLen, UINT8 *pszConfigFileName);
INT32 GetConfigFileIntValue(UINT8 *pszSectionName, UINT8 *pszKeyName, UINT32 iDefaultVal, UINT8 *pszConfigFileName);
INT32 main();

/**********************************************************************
* 功能描述:主函数
* 输入参数:无
* 输出参数:无
* 返 回 值:无
* 其它说明:无
* 修改日期         版本号         修改人            修改内容
* ---------------------------------------------------------------
* 20150507        V1.0     Zhou Zhaoxiong          创建
***********************************************************************/
INT32 main()
{
    T_EmployeeInfo tEmployeeInfo = {0};
    T_EmployerInfo tEmployerInfo = {0};

    // 获取并打印员工信息
    // 获取员工姓名
    GetConfigFileStringValue("EMPLOYEEINFO", "EmployeeName", "", tEmployeeInfo.szEmployeeName, sizeof(tEmployeeInfo.szEmployeeName), "Config.ini");

    // 获取员工年龄
    tEmployeeInfo.iEmployeeAge = GetConfigFileIntValue("EMPLOYEEINFO", "EmployeeAge", 20, "Config.ini");
    if (tEmployeeInfo.iEmployeeAge == -1)  // 判断获取到的年龄是否正确
    {
        printf("Get EmployeeAge failed!\n");
        return -1;
    }

    // 打印读取到的员工姓名和年龄
    printf("EmployeeName is %s, EmployeeAge is %d\n", tEmployeeInfo.szEmployeeName, tEmployeeInfo.iEmployeeAge);

    // 获取并打印雇主信息
    // 获取雇主姓名
    GetConfigFileStringValue("EMPLOYERINFO", "EmployerName", "", tEmployerInfo.szEmployerName, sizeof(tEmployerInfo.szEmployerName), "Config.ini");

    // 获取员工年龄
    tEmployerInfo.iEmployerAge = GetConfigFileIntValue("EMPLOYERINFO", "EmployerAge", 30, "Config.ini");
    if (tEmployerInfo.iEmployerAge == -1)  // 判断获取到的年龄是否正确
    {
        printf("Get EmployerAge failed!\n");
        return -1;
    }

    // 打印读取到的员工姓名和年龄
    printf("EmployerName is %s, EmployerAge is %d\n", tEmployerInfo.szEmployerName, tEmployerInfo.iEmployerAge);

    return 0;
}

/**********************************************************************
* 功能描述: 获取配置文件完整路径(包含文件名)
* 输入参数: pszConfigFileName-配置文件名
             pszWholePath-配置文件完整路径(包含文件名)
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
* 修改日期        版本号         修改人       修改内容
* ------------------------------------------------------------------
* 20150507       V1.0     Zhou Zhaoxiong     创建
********************************************************************/
void GetCompletePath(UINT8 *pszConfigFileName, UINT8 *pszWholePath)
{
    UINT8 *pszHomePath      = NULL;
    UINT8  szWholePath[256] = {0};

    // 先对输入参数进行异常判断
    if (pszConfigFileName == NULL || pszWholePath == NULL)
    {
        printf("GetCompletePath: input parameter(s) is NULL!\n");
        return;
    }

    pszHomePath = (UINT8 *)getenv("HOME");     // 获取当前用户所在的路径
    if (pszHomePath == NULL)
    {
        printf("GetCompletePath: Can't find home path!\n");
        return;
    }

    // 拼装配置文件路径
    snprintf(szWholePath, sizeof(szWholePath)-1, "%s/zhouzx/GetConfig/%s", pszHomePath, pszConfigFileName);

    strncpy(pszWholePath, szWholePath, strlen(szWholePath));
}

/**********************************************************************
* 功能描述: 获取具体的字符串值
* 输入参数: fp-配置文件指针
             pszSectionName-段名, 如: GENERAL
             pszKeyName-配置项名, 如: EmployeeName
             iOutputLen-输出缓存长度
* 输出参数: pszOutput-输出缓存
* 返 回 值: 无
* 其它说明: 无
* 修改日期         版本号        修改人       修改内容
* ------------------------------------------------------------------
* 20150507       V1.0     Zhou Zhaoxiong     创建
********************************************************************/
void GetStringContentValue(FILE *fp, UINT8 *pszSectionName, UINT8 *pszKeyName, UINT8 *pszOutput, UINT32 iOutputLen)
{
    UINT8  szSectionName[100]    = {0};
    UINT8  szKeyName[100]        = {0};
    UINT8  szContentLine[256]    = {0};
    UINT8  szContentLineBak[256] = {0};
    UINT32 iContentLineLen       = 0;
    UINT32 iPositionFlag         = 0;

    // 先对输入参数进行异常判断
    if (fp == NULL || pszSectionName == NULL || pszKeyName == NULL || pszOutput == NULL)
    {
        printf("GetStringContentValue: input parameter(s) is NULL!\n");
        return;
    }

    sprintf(szSectionName, "[%s]", pszSectionName);
    strcpy(szKeyName, pszKeyName);

    while (feof(fp) == 0)
    {
        memset(szContentLine, 0x00, sizeof(szContentLine));
        fgets(szContentLine, sizeof(szContentLine), fp);      // 获取段名

        // 判断是否是注释行(以;开头的行就是注释行)或以其他特殊字符开头的行
        if (szContentLine[0] == ';' || szContentLine[0] == '\r' || szContentLine[0] == '\n' || szContentLine[0] == '\0')
        {
            continue;
        }

        // 匹配段名
        if (strncasecmp(szSectionName, szContentLine, strlen(szSectionName)) == 0)
        {
            while (feof(fp) == 0)
            {
                memset(szContentLine,    0x00, sizeof(szContentLine));
                memset(szContentLineBak, 0x00, sizeof(szContentLineBak));
                fgets(szContentLine, sizeof(szContentLine), fp);     // 获取字段值

                // 判断是否是注释行(以;开头的行就是注释行)
                if (szContentLine[0] == ';')
                {
                    continue;
                }

                memcpy(szContentLineBak, szContentLine, strlen(szContentLine));

                // 匹配配置项名
                if (strncasecmp(szKeyName, szContentLineBak, strlen(szKeyName)) == 0)
                {
                    iContentLineLen = strlen(szContentLine);
                    for (iPositionFlag = strlen(szKeyName); iPositionFlag <= iContentLineLen; iPositionFlag ++)
                    {
                        if (szContentLine[iPositionFlag] == ' ')
                        {
                            continue;
                        }
                        if (szContentLine[iPositionFlag] == '=')
                        {
                            break;
                        }

                        iPositionFlag = iContentLineLen + 1;
                        break;
                    }

                    iPositionFlag = iPositionFlag + 1;    // 跳过=的位置

                    if (iPositionFlag > iContentLineLen)
                    {
                        continue;
                    }

                    memset(szContentLine, 0x00, sizeof(szContentLine));
                    strcpy(szContentLine, szContentLineBak + iPositionFlag);

                    // 去掉内容中的无关字符
                    for (iPositionFlag = 0; iPositionFlag < strlen(szContentLine); iPositionFlag ++)
                    {
                        if (szContentLine[iPositionFlag] == '\r' || szContentLine[iPositionFlag] == '\n' || szContentLine[iPositionFlag] == '\0')
                        {
                            szContentLine[iPositionFlag] = '\0';
                            break;
                        }
                    }

                    // 将配置项内容拷贝到输出缓存中
                    strncpy(pszOutput, szContentLine, iOutputLen-1);
                    break;
                }
                else if (szContentLine[0] == '[')
                {
                    break;
                }
            }
            break;
        }
    }
}

/**********************************************************************
* 功能描述: 从配置文件中获取字符串
* 输入参数: pszSectionName-段名, 如: GENERAL
             pszKeyName-配置项名, 如: EmployeeName
             pDefaultVal-默认值
             iOutputLen-输出缓存长度
             pszConfigFileName-配置文件名
* 输出参数: pszOutput-输出缓存
* 返 回 值: 无
* 其它说明: 无
* 修改日期        版本号         修改人       修改内容
* ------------------------------------------------------------------
* 20150507       V1.0     Zhou Zhaoxiong     创建
********************************************************************/
void GetConfigFileStringValue(UINT8 *pszSectionName, UINT8 *pszKeyName, UINT8 *pDefaultVal, UINT8 *pszOutput, UINT32 iOutputLen, UINT8 *pszConfigFileName)
{
    FILE  *fp                    = NULL;
    UINT8  szWholePath[256]      = {0};

    // 先对输入参数进行异常判断
    if (pszSectionName == NULL || pszKeyName == NULL || pszOutput == NULL || pszConfigFileName == NULL)
    {
        printf("GetConfigFileStringValue: input parameter(s) is NULL!\n");
        return;
    }

    // 获取默认值
    if (pDefaultVal == NULL)
    {
        strcpy(pszOutput, "");
    }
    else
    {
        strcpy(pszOutput, pDefaultVal);
    }

    // 打开配置文件
    GetCompletePath(pszConfigFileName, szWholePath);
    fp = fopen(szWholePath, "r");
    if (fp == NULL)
    {
        printf("GetConfigFileStringValue: open %s failed!\n", szWholePath);
        return;
    }

    // 调用函数用于获取具体配置项的值
    GetStringContentValue(fp, pszSectionName, pszKeyName, pszOutput, iOutputLen);

    // 关闭文件
    fclose(fp);
    fp = NULL;
}

/**********************************************************************
* 功能描述: 从配置文件中获取整型变量
* 输入参数: pszSectionName-段名, 如: GENERAL
             pszKeyName-配置项名, 如: EmployeeName
             iDefaultVal-默认值
             pszConfigFileName-配置文件名
* 输出参数: 无
* 返 回 值: iGetValue-获取到的整数值   -1-获取失败
* 其它说明: 无
* 修改日期         版本号       修改人        修改内容
* ------------------------------------------------------------------
* 20150507       V1.0     Zhou Zhaoxiong     创建
********************************************************************/
INT32 GetConfigFileIntValue(UINT8 *pszSectionName, UINT8 *pszKeyName, UINT32 iDefaultVal, UINT8 *pszConfigFileName)
{
    UINT8  szGetValue[512] = {0};
    INT32  iGetValue       = 0;

    // 先对输入参数进行异常判断
    if (pszSectionName == NULL || pszKeyName == NULL || pszConfigFileName == NULL)
    {
        printf("GetConfigFileIntValue: input parameter(s) is NULL!\n");
        return -1;
    }

    GetConfigFileStringValue(pszSectionName, pszKeyName, NULL, szGetValue, 512-1, pszConfigFileName);    // 先将获取的值存放在字符型缓存中

    if (szGetValue[0] == '\0' || szGetValue[0] == ';')    // 如果是结束符或分号, 则使用默认值
    {
        iGetValue = iDefaultVal;
    }
    else
    {
        iGetValue = atoi(szGetValue);
    }

    return iGetValue;
}

七、文件上传
在Windows下将程序编写好之后,使用filezilla软件将“GetConfig.c”代码文件和“Config.ini”配置文件上传到“/home/zhou/zhouzx/GetConfig”目录下。

八、文件编译及运行结果
使用SecureCRT软件登录到Linux下,转到“/home/zhou/zhouzx/GetConfig”目录下,执行“gcc -g -o GetConfig GetConfig.c”命令,生成“GetConfig”。然后再执行“GetConfig”命令,程序运行结果如下:

~/zhouzx/GetConfig> gcc -g -o GetConfig GetConfig.c
~/zhouzx/GetConfig> GetConfig
EmployeeName is wang, EmployeeAge is 25
EmployerName is zhou, EmployerAge is 38

九、总结
本文对Linux下配置文件读取操作的整个流程进行了详细的介绍,并给出了实现该操作的C代码。程序中的GetConfigFileStringValue和GetConfigFileIntValue函数可作为API供其它需要读取配置文件的程序调用。



本人微信公众号:zhouzxi,请扫描以下二维码:

时间: 2025-01-21 06:10:17

Linux下配置文件读取操作流程及其C代码实现的相关文章

Linux下c++程序内存泄漏检测代码范例

Linux下对于程序内存泄漏检测的方法很多,最常用的的莫过于使用valgrind工具.但是valgrind相当于让程序在虚拟机中运行,会带 来较大的系统资源开销,还会对程序的运行效率产生较大影响,对于那种资源占用大的程序,如果需要长时间运行才能暴露的泄漏问题,它就显得不太好用. linux下的c++程序中自己实现一个轻量级的泄漏检测代码其实是比较方便的,下面我就给出一个简单的范例,并作简单的说明.当然,我们还是应该提倡使用共享指针,用共享指针自动管理内存可以避免内存泄漏这样的不必要的麻烦. 基本

IE下JS读取xml文件示例代码_javascript技巧

使用JS读取xml文件,这里暂只考虑IE浏览器 step1 创建DOM对象 复制代码 代码如下: function createDom() { var xmlDoc = null; try { //IE if (typeof arguments.callee.activeXString != 'string') { var versions = [ "MSXML2.DOMDocument.6.0", "MSXML2.DOMDocument.3.0", "M

Linux下Python获取IP地址的代码_python

<lnmp一键安装包>中需要获取ip地址,有2种情况:如果服务器只有私网地址没有公网地址,这个时候获取的IP(即私网地址)不能用来判断服务器的位置,于是取其网关地址用来判断服务器在国内还是国外(脚本为了使国内用户快速下载,yum源自动设置成163,这个情况就需要获取网关地址):如果服务器有公网地址,这时获取的IP地址可用来直接判断服务器地理位置. 获取服务器IP,如果有公网地址就取公网地址,没有公网地址就取私网网址 下面是之前我用shell来获取本地IP脚本: IP=`ifconfig | g

Linux下一个简单的日志系统的设计及其C代码实现

1.概述 在大型软件系统中,为了监测软件运行状况及排查软件故障,一般都会要求软件程序在运行的过程中产生日志文件.在日志文件中存放程序流程中的一些重要信息,包括:变量名称及其值.消息结构定义.函数返回值及其执行情况.脚本执行及调用情况等.通过阅读日志文件,我们能够较快地跟踪程序流程,并发现程序问题.因此,熟练掌握日志系统的编写方法并快速地阅读日志文件,是对一个软件开发工程师的基本要求. 本文详细地介绍了Linux下一个简单的日志系统的设计方法,并给出了其C代码实现.本文为相关开发项目Linux下软

Linux下时间范围判断的程序流程及其C代码实现

一.概述 在实际的软件开发项目中,经常会遇到需要判断时间范围的情况.例如,某软件要在某段时间内执行对过期数据的清理,在其它时间段不执行.为了体现程序的灵活性,一般都是在配置文件中设置时间段的始末值,这样可根据软件的实际安装环境进行配置.本文介绍判断当前时间是否在配置的时间范围内的程序流程,并给出了C代码实现.具体的需求描述如下: 在配置文件中按需配置某一开始时间和结束时间,编写程序判断当前系统时间是否在配置时间的范围之内.配置的时间格式为:HH:MM(小时:分),如08:30表示8点30分. 二

Linux下程序启动之后的初始化---检查配置文件及读取日志配置项的值

概述 最近,我对本开发组的几位新员工所编写的程序进行了代码走查,发现他们的代码都有一个共同的问题:缺少必要的初始化.在本文中,我将详细介绍程序在启动时所必须要进行的初始化操作,并用实际的C代码予以说明. 对于一般的程序来说,在启动时所必须要进行的初始化操作有两个:检查配置文件及读取日志配置项.对于检查配置文件,主要检查配置文件是否是规定的文件类型(后缀是否正确)及是否存放在了规定的目录下(一般存放在当前用户的etc目录下):对于读取日志配置项,主要将写日志文件相关的参数(如日志级别.日志文件最大

poi3 11 excel2007-poi3.11 linux 下解析了不excel2007 但win7下没问题

问题描述 poi3.11 linux 下解析了不excel2007 但win7下没问题 使用spring mvc 上传文件.POI 在linux 64位下解析不了excel2007文件.而win7 32位下没问题.使用wps创建的excel都没问题.经过调试发现window下,上传文件的时候文件头是847d1caa,当写入本地再读取后会将文件头改为504b0304(zip格式),所以可以正常运行.但linux下再读取文件头也不会变,导致POI识别不了.代码如下: @RequestMapping(

python在windows和linux下获得本机本地ip地址方法小结_python

本文实例总结了python在windows和linux下获得本机本地ip地址方法.分享给大家供大家参考.具体分析如下: python的socket包含了丰富的函数和方法可以获得本机的ip地址信息,socket对象的gethostbyname方法可以根据主机名获得本机ip地址,socket对象的gethostbyname_ex方法可以获得本机所有ip地址列表 第一种方法:通过socket.gethostbyname方法获得 import socket localIP = socket.gethos

Linux下重置MySQL密码

Linux下重置MySQL密码 据有关资料显示,人能记住的密码一般不多,很多时候人都是多账户同密码的办法来设置密码的.但一般来说,经常需要接触的账户密码是不会忘记的.但偏偏也有可能有忘记的时候,下面就介绍下在Linux环境下忘记MySQL密码的解决方法.其实很简单,只需要六个步骤就可以解决问的.不多说闲话,进入话题: 1.关闭MySQL服务: service mysqld stop 2.执行下面命令,跳出安全模式,当然,这条命令大概只在localhost的时候有效. /usr/local/mys