当前位置:  开发笔记 > 后端 > 正文

C(Unix)中基于文件的配置处理

如何解决《C(Unix)中基于文件的配置处理》经验,为你挑选了6个好方法。

这可能是编程时最常见的任务/问题之一; 您需要在某处存储应用程序的配置.

在我尝试创建Web服务器或其他应用程序时,我希望尽可能保持代码清洁,因为我对编程的主要兴趣是架构.这导致我希望将配置存储在文件中,无需重新编译软件即可对其进行更改.

我不是来重新发明轮子或类似的东西,所以我想做的是在C on*nix上创建一个配置阅读器.配置看起来可能与任何其他软件的配置非常相似; Apache,vsftpd,MySQL等

基本问题是:如何从文本文件中读取并有效地处理每一行(在纯C中)?我需要使用fgetc()和处理每个字符吗?



1> Malx..:

嗯有LibConfig.

我在Wiki中找到了它


那么这是一个非常好的库,如果我不想了解底层结构,我可能会使用它.

2> Jonathan Lef..:

各种各样的人给出了相当不错的建议 - Pure-FTP示例很有意思.

您还应该阅读ES Raymond的TAOUP(Unix编程艺术).它有一些示例 - 大量的配置文件.它还概述了配置文件的规范习语.例如,您应该允许'#'在行的末尾开始注释,并忽略空行.如果配置文件包含您不理解的行 - 是否要忽略并继续静默,或者是否要抱怨,您还应该决定要做什么.(我更喜欢抱怨的东西;然后我知道为什么我刚刚添加的东西没有任何影响 - 而沉默忽略意味着我不知道我刚添加的条目是否有任何影响.)

另一个问题是找到配置文件.您是通过编译位置,使用环境变量覆盖的默认安装位置,还是通过其他一些魔法来实现的?确保有一个命令行选项允许绝对指定配置文件 - 甚至考虑将其作为唯一的方法.

否则,在广泛的范围内,保持简单,每个人都会更快乐.



3> Charlie Mart..:

好的,让我们点击其他部分.你需要考虑你想要的"语言".在UNIX世界中,规范版本可能是以空格分隔的文本(思考/etc/hosts)或":"分隔文本(如/etc/passwd).

你有几个选择,在某种意义上最简单的是使用scanf(3).再次阅读手册页以获取详细信息,但是如果行条目是类似的话

port    100

然后你会找到类似的东西

char inbuf[MAXLINE];
int  val;

scanf("%s %d\n", &inbuf[0], &val);

如果编写一个简单的FSA解析,可以获得更大的灵活性:从行中一次读取一个字符,并使用有限自动机来定义要执行的操作.


如果字段长于MAXLINE,则容易受到缓冲区溢出的影响,对吧?
@boramalper所以,是的,你是对的,我没有谈论缓冲区溢出漏洞,同时向新程序员解释如何读取基本文本文件.我也没有解释字节序.或分段错误.我经常注意到我教授编程的一个优点是我还记得我什么时候都不知道.
@boramalper他询问是否需要使用`fgetc`或者什么的部分.
@CharlieMartin“是的。还有吗?毕竟,这是关于制作配置文件的讨论。” 这是您的攻击。根据定义,几乎所有配置文件都暴露于外界,并且用户和其他第三方程序可以通过任何方式对其进行修改。因此,这不仅仅是关于“毕竟”制作配置文件的讨论。有关如何正确使用`scanf`的信息,请参见/sf/ask/17360801/。

4> Charlie Mart..:

好的,这是一个C代码的真实例子:

/* demo-fgets -- read a "demo.text", copy to stdout with line
   numbers. */

#include 
#include 

#define MAXLINE 100

FILE * fp;
char bufr[MAXLINE];

extern int errno ;

int main(int argc, char ** argv){
    int count = 0 ;
    if((fp = fopen("demo.text","r")) != NULL){
        /* then file opened successfully. */
        while(fgets(bufr,MAXLINE,fp)!=NULL){
            /* then no read error */
            count +=1;
            printf("%d: %s",     /* no "\n", why? */
                   count, bufr);
        }
        /* fgets returned null */
        if(errno != 0){
            perror(argv[0]);    /* argv[0]?  Why that? */
            exit(1);
        }
        exit(0);                /* EOF found, normal exit */
    } else {                    /* there was an error on open */
        perror(argv[0]);
        exit(1);
    }
}

我用这个输入文件运行它:

520 $ cat demo.text 
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum
aliquet augue id quam. Sed a metus. Quisque sit amet quam. Sed id
ante. In egestas est non mi. Sed vel velit non elit vehicula
viverra. Curabitur eget tortor in ipsum vulputate
faucibus. Suspendisse imperdiet mauris at nibh. Sed interdum. Maecenas
vulputate, massa vel placerat mattis, ante est tincidunt sem, in
sollicitudin velit lacus non tortor. Etiam sagittis consequat nisl. 

Vestibulum id leo quis mauris gravida placerat. Donec aliquet justo a
tortor. Etiam nisi nibh, auctor non, luctus et, aliquam vitae,
metus. Cum sociis natoque penatibus et magnis dis parturient montes,
nascetur ridiculus mus. Nunc lacinia quam a ligula. Nulla quis nisi eu
nunc imperdiet cursus. Nunc vitae nisi vitae tellus posuere
sollicitudin. Nunc suscipit, dui ac interdum euismod, pede nisl varius
dui, sed mattis libero mauris eu felis. Nam mattis dui eget
nunc. Suspendisse malesuada, pede eget posuere pellentesque, neque
eros pretium nibh, ut blandit dui leo dapibus orci. Etiam lacinia
lectus at orci. Donec ligula lacus, sagittis nec, sodales et,
fringilla lobortis, eros. Etiam sit amet nulla. Aliquam mollis pede id
enim. Etiam ligula felis, pulvinar nec, vestibulum molestie, interdum
ut, urna. Ut porta ullamcorper diam. Nullam interdum arcu. 

Pellentesque habitant morbi tristique senectus et netus et malesuada
fames ac turpis egestas. Etiam eu enim quis sem accumsan
tristique. Proin non sem. Etiam quis ante. Aenean ornare pellentesque
dolor. Praesent sodales. Cras dui velit, scelerisque a, accumsan a,
vestibulum in, dui. Pellentesque sed sapien. Etiam augue est,
convallis eget, egestas vel, molestie id, turpis. Cum sociis natoque
penatibus et magnis dis parturient montes, nascetur ridiculus
mus. Cras posuere lorem eu diam. Ut ultricies velit. Nunc imperdiet
suscipit mauris. Vestibulum molestie elit id risus. Phasellus et
purus. Vestibulum id mauris. Fusce gravida elit quis turpis. Aliquam
ut est. 

Sed in mauris eu nulla rhoncus suscipit. Nam id dolor sit amet turpis
placerat sodales. Nunc ipsum. Quisque diam tellus, dapibus non,
interdum at, aliquam sit amet, tellus. Donec non pede eget massa
aliquam semper. Quisque dictum lacinia ipsum. Fusce magna purus,
mattis id, commodo et, lobortis eu, arcu. Vestibulum viverra neque a
nulla. Cum sociis natoque penatibus et magnis dis parturient montes,
nascetur ridiculus mus. Pellentesque vel felis in ligula blandit
auctor. Quisque quam. Curabitur turpis. Morbi molestie augue a
nisi. Nulla sollicitudin sagittis elit. Suspendisse in odio sed magna
dictum vestibulum. Duis facilisis lorem eget neque. Proin sit amet
urna eget velit scelerisque aliquam. Pellentesque imperdiet. Nullam
sapien. Nullam placerat ipsum eget metus. 

Mauris ornare risus eu velit. Morbi bibendum diam in sem. Morbi
aliquet nisl sit amet quam. Donec ornare sagittis nibh. Fusce ac
lectus. Sed sit amet risus. Integer facilisis commodo
sem. Pellentesque facilisis. Donec libero. Lorem ipsum dolor sit amet,
consectetur adipiscing elit.



5> Charlie Mart..:

有很多方法.你并不需要使用龟etc.您应该阅读stdio手册页,但规范的事情是用fopen(3)打开文件,然后使用fgets(3)读取一次读取一行.这看起来像是这样的:

#include 

FILE * fp ;
char bufr[MAXLINE];

if((fp = fopen(filename, "r") != NULL){
    while(! feof(fp)){
         fgets(bufr, MAXLINE, fp);
         /* Do stuff */
    }
} else {
    /* error processing, couldn't open file */
}

您还可以在Sourceforge上查看libini.



6> Ana Betts..:

为什么你会永远从头开始编写这个代码,它已经做了这么多次; 找到一个好的F/OSS实现并使用它.

如何从文本文件中读取并有效地处理每一行

不要担心效率,读取配置文件无关紧要.寻求简单性和可维护性.

推荐阅读
sx-March23
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有