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

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

虽然即时通讯试图创build一个networking服务器和/或其他应用程序,我想保持尽可能干净的代码,因为我的主要兴趣在编程是架构。 这导致我希望将configuration存储在一个可以更改的文件中,而不必重新编译软件。

我不是在这里重新发明轮子或类似的东西,所以我想要做的是在* nix的C上创build一个configuration阅读器。 configuration可能看起来很像其他软件configuration。 Apache,vsftpd,mysql等

基本的问题是:如何从Textfile中读取并有效处理每行(在Pure C中)? 我需要使用fgetc()并处理每个字符?

好吧,让我们打另一部分。 你需要考虑你想作为你的“语言”。 在UNIX世界中,规范版本可能是以空格分隔的文本(想/etc/hosts )或“:”分隔文本(如/etc/passwd )。

你有几个选项,最简单的就是使用scanf(3)。 再次,阅读手册页的细节,但如果行条目是类似的

 port 100 

那么你会寻找类似的东西

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

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

嗯有LibConfig 。

我在Wiki中找到它

不同的人给出了相当好的建议 – Pure-FTP的例子很有趣。

您还应该阅读ES Raymond的TAOUP (Unix编程艺术)。 它有很多配置文件的例子。 它还概述了配置文件的规范成语。 例如,您应该允许“#”在行尾开始注释,并忽略空白行。 如果配置文件中有一行你不明白的行 – 你是否忽略并继续静默,还是抱怨,你也应该决定要做什么。 (我更喜欢抱怨的东西;然后我知道为什么我刚刚添加的东西没有任何效果 – 而沉默的忽略意味着我不知道我刚刚添加的条目是否有任何作用。)

另一个问题是找到配置文件。 你是通过编译的位置,通过默认的安装位置来重写环境变量,还是通过其他一些魔法? 确保有一个命令行选项允许绝对地指定配置文件,甚至考虑做这个唯一的方法。

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

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

 #include <stdio.h> 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 。

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

 /* demo-fgets -- read a "demo.text", copy to stdout with line numbers. */ #include <stdio.h> #include <stdlib.h> #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. 

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

你如何从一个文本文件读取和有效地处理每一行

不要担心效率,阅读配置文件并不重要。 去代替简单性和可维护性。

又一个解决方案 – Pure-ftpd

与许多守护进程不同,Pure-FTPd不会读取任何配置文件。 相反,它使用命令行选项。 …在服务器中添加配置文件的解析器是一个坏主意。 它放慢了一切,需要资源,没有任何东西。

而选项有getopt

我会这样做的方式(伪代码):

 while(there is input) { get one line; if (it is empty line || it beings with spaces followed by a '#') { skip this line, either empty or it's a comment; } find the position of the token that splits option name and its value; copy the option name and its value to separate variables; removing spaces before and after these variables if necessary; if (option == option1) { parse value for option 1; } else if (option == option2) { parse value for option 2; } else { handle unknown option name; } check consistency of options if necessary; } 

注意,在编写配置文件时,部分代码(检查空行,注释和变量周围的空格)是给你额外的灵活性。 例如,你不会意外地在这里和那里留下额外的空间,从而使程序崩溃。

这是假设你有配置文件,如下所示:

 # comment for option 1 option1 = value1 # comment for option 2 option2 = value2 ... 

在GNU LibC中还有getline()函数和好友

你有没有考虑将配置值存储为环境变量? :)配置文件将是你的程序之前运行的shell脚本。 (实际上shell脚本会执行它来保存变量)。 这样,你使用shell作为配置解析器:)

使用http://www.google.com/codesearch和“读取配置&#x201D;

请参阅httpd的示例

我刚才在C中写了一个干净的,依赖关系较小的事件驱动的INI文件解析器。 我决定把它扔进一个公共的汞储存库 。 它是麻省理工学院许可的,所以你可以随意使用它在任何你喜欢的地方。