ini文件的基本格式如下。
1: [Section1]
2: Name1=Value1
3: Name2=Value2
4:
5: [Section2]
6: Name1=Value1
7: Name2=Value2
ini文件由section组成,可以在每个section中定义若干属性及其值。
ini文件是一种比较简单的信息管理方式,内容简单,格式简单,使用方便。 而且内容都是ASCII,很直观。
在许多情况下,可能会使用ini文件。 例如,我们编写的程序希望用户进行详细的结构时,或者希望程序具有保存设定的能力时。
在双向链表中操作ini的代码实现方法如下所示。
我用三个结构体描述了一个ini文件:
1: typedef struct ini_item_t {
2: struct ini_item_t *prev;
3: struct ini_item_t *next;
4: char *name;
5: char *value;
6: } INIITEM,*LPINIITEM;
7:
8: typedefstructini _ section _ t {
9: struct ini_section_t *prev;
10: struct ini _ section _ t * next;
11: char *name;
12: int itemCount;
13: struct ini _ item _ t * first _ item;
1: struct ini _ item _ t * last _ item;
15: } INISECTION,*LPINISECTION;
16:
17: typedefstructini _ file _ t {
18: char *name;
19: int sectionCount;
2033 360 struct ini _ section _ t * first _ section;
2: struct ini _ section _ t * last _ section;
22:输入标志;
23: char mode[8];
24: } INIFILE,*LPINIFILE;
INIFILE用于描述ini文件,而内部的first_section和last_section用于表示链表。 此链表的成员节点是INISECTION,它描述了当前包含在此ini文件中的section部分。
INISECTION用于描述ini文件中的section,它本身是链表的节点,其内部的first_item和last_item用于表示不同的链表。 此链表描述当前包含在此section中的条目。
INIITEM是最基础的结构体定义,记述了item的信息。
INIFILE表示一个ini文件,在此INIFILE中可能有几个section。 这些section形成链表。
初始化INIFILE的过程如下。
1: staticlpinifileini _ createinistruct (const char * name )。
2: {
3: lpinifileinifile=(LP inifile ) malloc ) sizeof(inifile );
43360inifile-name=(char* ) malloc ) strlen(name ) 1;
3:strcpy(inifile-name,name );
6: inifile-first _ section=空;
7: inifile-last _ section=null;
8: iniFile-sectionCount=0;
9: iniFile-flag=0;
10:返回文件;
11: }
12:
13: staticvoidini _ destryinistruct (lpinifileinifile ) )。
14: {
15: lpinisectionsec=inifile-first _ section;
1:帧(inifile-name );
17:while(sec )。
18: {
1933 360 lpinisectiontmp=sec-next;
20:ini_Delsection(inifile,sec );
21: sec=
tmp;22: }
23: free(iniFile);
24: }
在初始化一个INIFILE结构体的过程中,主要是为INIFILE结构体内的数据分配空间,并将INIFILE里的INISECTION链表设置为空;
在某个section内,可能包含了若干个item,这些item在当前section内也形成了一个链表;
初始化一个INISECTION的过程如下:
1: static LPINISECTION ini_addSection(LPINIFILE iniFile, const char *name)
2: {
3: LPINISECTION sec = (LPINISECTION)malloc(sizeof(INISECTION));
4: sec->name = (char *)malloc(strlen(name) + 1);
5: strcpy(sec->name, name);
6: sec->first_item = NULL;
7: sec->last_item = NULL;
8: sec->itemCount = 0;
9: add_node((void**)&(iniFile->first_section), (void**)&(iniFile->last_section), sec);
10: return sec;
11: }
12:
13: static void ini_delSection(LPINIFILE iniFile, LPINISECTION sec)
14: {
15: LPINIITEM item = sec->first_item;
16: free(sec->name);
17: while(item)
18: {
19: LPINIITEM tmp = item->next;
20: ini_delItem(sec, item);
21: item = tmp;
22: }
23: del_node((void**)&(iniFile->first_section), (void**)&(iniFile->last_section), sec);
24: free(sec);
25: }
当需要向INIFILE添加一个section时,一方面需要创建出来INISECTION,并添加到INIFILE的链表内,另一方面,要初始化INISECTION内的INIITEM链表。
最后是item的操作:
1: static LPINIITEM ini_addItem(LPINISECTION iniSection, const char *name, const char *value)
2: {
3: LPINIITEM item = (LPINIITEM)malloc(sizeof(INIITEM));
4: item->name = (char *)malloc(strlen(name) + 1);
5: strcpy(item->name, name);
6: item->value = (char *)malloc(strlen(value) + 1);
7: strcpy(item->value, value);
8: add_node((void**)&(iniSection->first_item), (void**)&(iniSection->last_item), item);
9: iniSection->itemCount++;
10: return item;
11: }
12:
13: static void ini_delItem(LPINISECTION iniSection, LPINIITEM item)
14: {
15: free(item->name);
16: free(item->value);
17: del_node((void**)&(iniSection->first_item), (void**)&(iniSection->last_item), item);
18: free(item);
19: iniSection->itemCount--;
20: }
以上有关链表的操作,都调用了《一个通用的双向链表管理程序》一文中介绍的通用双向链表管理程序。因为有了这个程序的存在,才使得对ini文件进行操作时,对于INISECTION链表和INIITEM链表可以使用相同的操作方法,调用相同的函数。
有了描述ini文件的数据结构之后,剩下的就是如何将ini文件解析成相应的数据结构了:
1: INIFILEHANDLE ini_open(const char *iniFile, const char *mode)
2: {
3: char lineBuf[1024];
4: LPINIFILE file;
5: LPINISECTION curSection = NULL;
6: FILE *fp;
7: fp = fopen(iniFile, mode);
8: if(fp == NULL)
9: return NULL;
10: file = ini_createIniStruct(iniFile);
11: strcpy(file->mode, mode);
12: while(fgets(lineBuf, 1023, fp))
13: {
14: char *p = strtrim(lineBuf);
15: int len = strlen(p);
16: if(strlen(p) <= 0)
17: continue;
18: else if(p[0] == '#')
19: continue;
20: else if((p[0] == '[') && (p[len - 1] == ']'))
21: {
22: p[len - 1] = ' ';
23: p = strtrim(&p[1]);
24: curSection = ini_addSection(file, p);
25: }
26: else
27: {
28: char *p2 = strchr(lineBuf, '=');
29: if(p2 == NULL)
30: {
31: ini_destryIniStruct(file);
32: file = NULL;
33: break;
34: }
35: *p2++ = ' ';
36: p = strtrim(p);
37: p2 = strtrim(p2);
38: ini_addItem(curSection, p, p2);
39: }
40: }
41: fclose(fp);
42: return (INIFILEHANDLE)file;
43: }
这个过程不复杂,主要是分析“[”和“]”界定符,以便判断section的入口,然后解析接下来的item,并添加到INISECTION中。
接着是将数据结构所描述的ini信息保存成一个ini文件:
1: static void ini_writeItem(FILE *fp, LPINIITEM item)
2: {
3: fprintf(fp, "%s=%sn", item->name, item->value);
4: }
5:
6: static void ini_writeSection(FILE *fp, LPINISECTION sec)
7: {
8: LPINIITEM item = sec->first_item;
9: fprintf(fp, "[%s]n", sec->name);
10: while(item)
11: {
12: ini_writeItem(fp, item);
13: item = item->next;
14: }
15: fprintf(fp, "n");
16: }
17:
18: int ini_SaveTo(INIFILEHANDLE ini, FILE *fp)
19: {
20: LPINIFILE iniFile = (LPINIFILE)ini;
21: LPINISECTION sec = iniFile->first_section;
22: if(fp == NULL)
23: return -1;
24: fprintf(fp, "# %sn", iniFile->name);
25: while(sec)
26: {
27: ini_writeSection(fp, sec);
28: sec = sec->next;
29: }
30: return 0;
31: }
基本上就是这个样子了,下面把API贴出来吧:
1: // INI句柄
2: typedef void *INIFILEHANDLE;
3: // 打开一个ini文件
4: // iniFile: ini文件路径
5: // mode: 打开方式, 与fopen的第二个参数意义相同
6: INIFILEHANDLE ini_open(const char *iniFile, const char *mode);
7: // 将ini文件另存到一个I/O流
8: int ini_SaveTo(INIFILEHANDLE ini, FILE *fp);
9: // 将ini文件另存为
10: int ini_saveAs(INIFILEHANDLE ini, const char *saveFile);
11: // 关闭ini文件
12: void ini_close(INIFILEHANDLE ini);
13: // 从ini文件读取一个字符串类型的属性值
14: char *ini_ReadString(INIFILEHANDLE ini, const char *secName, const char *itemName, char *outBuf, const char *Default);
15: // 从ini文件读取一个整数类型的属性值
16: int ini_ReadInt(INIFILEHANDLE ini, const char *secName, const char *itemName, int Default);
17: // 向ini文件写入一个字符串类型的属性值,如果ini文件没有该属性,则创建
18: int ini_WriteString(INIFILEHANDLE ini, const char *secName, const char *itemName, const char *value);
19: // 向ini文件写入一个整数类型的属性值,如果ini文件没有该属性,则创建
20: int ini_WriteInt(INIFILEHANDLE ini, const char *secName, const char *itemName, int Value);
http://lameck.blog.163.com/blog/static/38811374200921614436213/