Linux环境用C语言实现读取配置文件来区分产品的多个版本以及多个功能

一、前言

在公司从事嵌入式软件工作,应用层程序有QT平台的也有Android平台的,我主要负责QT方面的内容,系统为Linux。但公司的产品具有多个国家的版本,导致开机的动态画面、应用程序的菜单Logo、产品出厂厂商、公司网址也不一样,有的版本会带蓝牙,有的不带蓝牙,有的版本图像融合需要勾边,而有的不需要,在维护时极其不方便,如果应用程序修改了一个功能,所有版本都需要升级,那么升级小包的个数应该是 m * 2^2个,所以为了方便维护,减轻本部门以及测试组同事的工作量,把各个版本用一个小包与一个配置文件进行代替;即实现程序的可配置方式启动。
原理就是把配置文件放在相对应的路径,比如我测试就放在/home/目录下,在QT程序启动初始化参数的时候就开始读取配置文件,根据配置文件的参数来设置QT程序版本、蓝牙、融合勾边的全局变量参数,在实现加载资源的代码处添加if判断全局变量的参数,而执行不同的代码。同时,读取配置文件的字符串也能实现不同资源的加载,只要把与配置文件同名的文件资源放在一个目录下,用绝对路径调用该资源就行了。下面主要介绍读取配置文件的实现。

二、配置文件及读配置文件的程序

为保证读到的配置文件时正确的,要注意配置文件的格式,比如“=”前后是否有空格,图片名字一定要对应系统目录下资源图片的名字:
配置文件如下:

[Boot]
LogoImage = xxxx.jpg //开机Logo
[FactoryInfo]
China=1//版本
India=0
Trotect=0
Bluetooth=0//蓝牙
MergePlus=1//勾边 (我的程序只读到该行就break了,结束了while循环)
Company=0//公司厂商
Link=0//公司网址
SatLogo=0
Screensaver=0//屏保

#Company=0: 公司1111111111
#Company=1: 公司2222222222
#Company=2: 公司3333333333

#Link=0: http://www.公司1111111111
#Link=1: http://www.公司2222222222
#Link=2: http://www.公司3333333333

#Logo=0:on, screensaver-1.png, for 公司11111111111,Serial Num=9103xxxx
#Logo=1:off, screensaver-2.png, for 公司2222222222,Serial Num=P6201xxxx
#Logo=2:off, screensaver-3.png, for 公司3333333333,Serial Num=9103xxxx

#Screensaver=0:screensaver-1
#Screensaver=1:screensaver-2
#Screensaver=2:screensaver-3
#Screensaver=3:screensaver-4
#Screensaver=4:screensaver-5
#Screensaver=5:screensaver-6

读配置文件的程序

int TAnalysisView::read_conf(void)//QT类中的一个方法,也就跟一个函数差不多,用C语言实现
{
        char conffile[]="/home/FactoryInfo.conf";//设置配置文件的路径,我只是测试暂时放这个目录下
        int line = 0;
        char *str;
        FILE *fp;
        int value;
        if((fp = fopen(conffile,"r")) == NULL)//打开配置文件
        {
                 printf("cannot open this file\n");
                 return 1;
        }

        char buf[BUF_SIZE_CONF];/BUF_SIZE_CONF //常量不用在意
        memset(buf,0,BUF_SIZE_CONF);//初始化buf
        while((str = fgets(buf, BUF_SIZE_CONF, fp)) != NULL){//逐行读取
                char *entry_name;
                char *entry_value;
                line++;
                if (buf[BUF_SIZE_CONF - 2] != '\0') {
                        printf("%s: line %d too long\n", conffile, line);
                        break;
                }
                if (str==NULL || *entry_name == '#')//空行或者#不读取
                        continue;
                entry_name = strsep(&str, "=");//分解字符串为一组字符串
                if (strcasecmp(entry_name, "China") == 0) {//忽略大小写比较字符串
                        entry_value = strsep(&str, "\0");
                        value = atoi(entry_value);//把字符串转换成整型数
                        if(value == 1){
                                //qWarning("[%s, %d]-----set_China true-----", __FILE__, __LINE__);
                                TGlobal::set_china(true);//设置全局变量参数
                        }
                } else if (strcasecmp(entry_name, "India") == 0) {
                        entry_value = strsep(&str, "\0");
             value = atoi(entry_value);
                        if(value == 1){
                                //qWarning("[%s, %d]-----set_India true-----", __FILE__, __LINE__);
                                TGlobal::set_India(true);//设置全局变量参数
                        }
                } else if (strcasecmp(entry_name, "Trotect") == 0) {
                        entry_value = strsep(&str, "\0");
                        value = atoi(entry_value);
                        if(value == 1){
                                //qWarning("[%s, %d]-----set_Trotect true-----", __FILE__, __LINE__);
                                TGlobal::set_Trotect(true);//设置全局变量参数
                        }
                } else if (strcasecmp(entry_name, "Bluetooth") == 0) {
                        entry_value = strsep(&str, "\0");
                        value = atoi(entry_value);
                        if(value == 1){
                                TGlobal::set_bluetooth(true);//设置全局变量参数
                        }
                } else if (strcasecmp(entry_name, "MergePlus") == 0) {
                        entry_value = strsep(&str, "\0");
                        value = atoi(entry_value);
                        if(value == 1){
                                TGlobal::set_mergePlus(true);//设置全局变量参数
                        }
                        break;//控制读取到该参数在退出while()循环
                }
                memset(buf,0,BUF_SIZE_CONF);
        }
        fclose(fp);
        return 0;
}

只需要在QT初始化时调用读取配置文件的方法即可。当然会也会遇到QT应用程序还没初始化就需要区分版本,可以直接用QT库中的类读取配置文件,如下:

Config cfg("FactoryInfo");//读取配置文件的名字,该文件应为FactoryInfo.conf,以.conf结尾
    cfg.setGroup("FactoryInfo");//读取配置文件内中的分组,FactoryInfo
    int lang = cfg.readNumEntry("China", 0);//读分组下面的China值为1

Config源码的config.h

#ifndef CONFIG_H
#define CONFIG_H

#include <qmap.h>
#include <qstringlist.h>

class Config
{
public:
    typedef QMap< QString, QString > ConfigGroup;

    Config( const QString &fn );
    ~Config();

    void setGroup( const QString &gname );
    void writeEntry( const QString &key, const QString &value );
    void writeEntry( const QString &key, int num );
#ifdef Q_HAS_BOOL_TYPE
    void writeEntry( const QString &key, bool b );
#endif
    void writeEntry( const QString &key, const QStringList &lst, const QChar &sep );

    QString readEntry( const QString &key, const QString &deflt = QString::null );
    int readNumEntry( const QString &key, int deflt = -1 );
    bool readBoolEntry( const QString &key, bool deflt = FALSE );
    QStringList readListEntry( const QString &key, const QChar &sep ); 

    void clearGroup();

    void write( const QString &fn = QString::null );

protected:
    void read();
    void parse( const QString &line );

    QMap< QString, ConfigGroup > groups;
    QMap< QString, ConfigGroup >::Iterator git;
    QString filename;

};

#endif

config.cpp的源码

#include "config.h"

#include <qfile.h>
#include <qfileinfo.h>
#include <qtextstream.h>

Config::Config( const QString &fn )
    : filename( fn )
{
    git = groups.end();
    read();
}

Config::~Config()
{
    write();
}

void Config::setGroup( const QString &gname )
{
    QMap< QString, ConfigGroup>::Iterator it = groups.find( gname );
    if ( it == groups.end() ) {
    ConfigGroup *grp = new ConfigGroup;
    git = groups.insert( gname, *grp );
    return;
    }
    git = it;
}

void Config::writeEntry( const QString &key, const QString &value )
{
    if ( git == groups.end() ) {
    qWarning( "no group set" );
    return;
    }
    ( *git ).insert( key, value );
}

void Config::writeEntry( const QString &key, int num )
{
    QString s;
    s.setNum( num );
    writeEntry( key, s );
}

#ifdef Q_HAS_BOOL_TYPE
void Config::writeEntry( const QString &key, bool b )
{
    QString s;
    s.setNum( ( int )b );
    writeEntry( key, s );
}
#endif

void Config::writeEntry( const QString &key, const QStringList &lst, const QChar &sep )
{
    QString s;
    QStringList::ConstIterator it = lst.begin();
    for ( ; it != lst.end(); ++it )
    s += *it + sep;
    writeEntry( key, s );
}

QString Config::readEntry( const QString &key, const QString &deflt )
{
    if ( git == groups.end() ) {
    //qWarning( "no group set" );
    return deflt;
    }
    ConfigGroup::Iterator it = ( *git ).find( key );
    if ( it != ( *git ).end() )
    return *it;
    else
    return deflt;
}

int Config::readNumEntry( const QString &key, int deflt )
{
    QString s = readEntry( key );
    if ( s.isEmpty() )
    return deflt;
    else
    return s.toInt();
}

bool Config::readBoolEntry( const QString &key, bool deflt )
{
    QString s = readEntry( key );
    if ( s.isEmpty() )
    return deflt;
    else
    return (bool)s.toInt();
}

QStringList Config::readListEntry( const QString &key, const QChar &sep )
{
    QString s = readEntry( key );
    if ( s.isEmpty() )
    return QStringList();
    else
    return QStringList::split( sep, s );
}

void Config::clearGroup()
{
    if ( git == groups.end() ) {
    qWarning( "no group set" );
    return;
    }
    ( *git ).clear();
}

void Config::write( const QString &fn )
{
    if ( !fn.isEmpty() )
    filename = fn;

    QFile f( filename );
    if ( !f.open( IO_WriteOnly ) ) {
    qWarning( "could not open for writing `%s'", filename.latin1() );
    git = groups.end();
    return;
    }

    QTextStream s( &f );
    QMap< QString, ConfigGroup >::Iterator g_it = groups.begin();
    for ( ; g_it != groups.end(); ++g_it ) {
    s << "[" << g_it.key() << "]" << "\n";
    ConfigGroup::Iterator e_it = ( *g_it ).begin();
    for ( ; e_it != ( *g_it ).end(); ++e_it )
        s << e_it.key() << " = " << *e_it << "\n";
    }

    f.close();
}

void Config::read()
{
    if ( !QFileInfo( filename ).exists() ) {
//  qWarning( "`%s' doesn't exist", filename.latin1() );
    git = groups.end();
    return;
    }

    QFile f( filename );
    if ( !f.open( IO_ReadOnly ) ) {
    qWarning( "could not open for reading `%s'", filename.latin1() );
    git = groups.end();
    return;
    }

    QTextStream s( &f );

    QString line;
    while ( !s.atEnd() ) {
    line = s.readLine();
    parse( line );
    }

    f.close();
}

void Config::parse( const QString &l )
{
    QString line = l.stripWhiteSpace();
    if ( line[ 0 ] == QChar( '[' ) ) {
    QString gname = line;
    gname = gname.remove( 0, 1 );
    if ( gname[ (int)gname.length() - 1 ] == QChar( ']' ) )
        gname = gname.remove( gname.length() - 1, 1 );
    ConfigGroup *grp = new ConfigGroup;
    git = groups.insert( gname, *grp );
    } else {
    if ( git == groups.end() ) {
        qWarning( "line `%s' out of group", line.latin1() );
        return;
    }
    QStringList lst = QStringList::split( '=', line );
    if ( lst.count() != 2 && line.find( '=' ) == -1 ) {
        qWarning( "corrupted line `%s' in group `%s'",
              line.latin1(), git.key().latin1() );
        return;
    }
    ( *git ).insert( lst[ 0 ].stripWhiteSpace(), lst[ 1 ].stripWhiteSpace() );
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值