INI文件格式说明
/*********************************************
ini文件说明
ini文件是文本文件,由节点(Section)和键值对(key=value)组成
以';'开头的行为注释
一般形式如下所示:
+--------------- test.ini -----------------+
| [Section1] |
| key1=value1 |
| key2=value2 |
| ;这是注释 |
| [Section2] |
| key3=value3 |
+------------------------------------------+
*********************************************/
更详细的介绍可见http://blog.chinaunix.net/uid-25885064-id-3327199.html
GetPrivateProfileString 从INI文件中读取String值
辅助函数 dupFile
1 //读取文件内容,保存到在heap区上申请的内存中dupFile
2 //成功返回内存地址,失败返回NULL
3 //参数fsize用于传出文件的内存区域的大小
4 char* dupFile(const char* FileName,long* fsize)
5 {
6 char* buf = NULL;
7 long size = 0;
8 //读取文件,因为ini文件通常都很小,所以一次全部读取了
9 FILE* fp = fopen(FileName,"r");
10 do{
11 if(fp == NULL){ //打开文件失败
12 //puts("打开文件失败");
13 break;
14 }
15 //获取文件大小
16 if(fseek(fp,0,SEEK_END)){
17 break; //fseek失败
18 }
19 size = ftell(fp); //获取当前偏移(文件长度)
20 if(size<0){break;}
21
22 //读取文件
23 fseek(fp,0,SEEK_SET);
24 buf = (char*)malloc(size+1);
25 if(buf == NULL){break;}
26 if(size == fread(buf,1,size,fp)){ //fread是阻塞模式,=
27 buf[size] = '\0';
28 //文件已经读取完成了
29 }else{ //万一失败了呢?
30 free(buf);
31 buf = NULL;
32 size = 0;
33 }
34 }while(0);
35 fclose(fp); //关闭文件
36 if(fsize != NULL){*fsize = size;}
37 return buf;
38 }
下面代码注释中写的不区分大小写是不对的,是区分大小写的。
/*函数说明:从FileName指定的ini文件中读取section节点下key键对应的value值(字符串)
*参数说明: Section: 节点名(不区分大小写)
* Key: 键名(不区分大小写)
* Default: 没有找到对应的value时的默认值
* ReturnedString: 接收找到的value的缓冲区
* nSize: 缓冲区的大小
* FileName: ini文件路径
*返回值:读取成功返回读取到的value的字符数。如果缓冲区不够大,value会被截断,返回nSize-1
*/
1 /*函数说明:从FileName指定的ini文件中读取section节点下key键对应的value值(字符串)GetPrivateProfileString
2 *参数说明: Section: 节点名(不区分大小写)
3 * Key: 键名(不区分大小写)
4 * Default: 没有找到对应的value时的默认值
5 * ReturnedString: 接收找到的value的缓冲区
6 * nSize: 缓冲区的大小
7 * FileName: ini文件路径
8 *返回值:读取成功返回读取到的value的字符数。如果缓冲区不够大,value会被截断,返回nSize-1
9 */
10
11 unsigned long GetPrivateProfileString(
12 const char* Section, //节点
13 const char* Key, //键
14 const char* Default, //默认值
15 char* ReturnedString, //接收获取值的目标缓冲区
16 unsigned long nSize, //目标缓冲区大小
17 const char* FileName //ini文件路径
18 )
19 {
20 FILE* fp; //文件指针
21 long fsize; //文件大小
22 long len; //
23 char* buf; //用于保存文件内容
24 char* psec; //保存节点位置
25 char* pkey; //指向文件中key位置
26 char* pval; //指向文件中value的位置
27 int iscomment; //用于判读是否是注释
28 do{
29 //获取文件内容
30 buf = dupFile(FileName,&fsize);
31 if(buf == NULL){break;}
32
33 //查找节点位置
34 char sbuf[1024];
35 sprintf(sbuf,"[%s]",Section);
36 psec = strstr(buf,sbuf); //查找节点
37 if(psec == NULL){
38 printf("没有找到节点 %s \n",sbuf);
39 break;//没有找到节点
40 }
41 //寻找key
42 pkey = psec; //查找的起点
43
44 //查找key
45 while((pkey = strstr(pkey,Key))!= NULL){
46 //找到了匹配的,进入
47 //判断找到的key是否与传入的一致(避免传入的是找到的前缀)
48 //如传入 "abc" 找到的是 "abcdef\n"
49 len = strlen(Key);
50 pval =pkey + len; //用pval指向pkey的尾部
51 char t = pval[0];
52 if(t == '=' || t==' ' || t=='\t'){
53 break; //找到了key,跳出本while
54 }
55 //没有找到key,去查找下一个匹配的
56 }// end while
57 if(pkey == NULL){
58 printf("没有找到Key:%s\n",Key);
59 break; //没有找到key,跳出
60 }
61 //确定找到的key是当前节点的(查找key和当前节点之间还有无节点)
62 pkey[-1] = '\0'; //从找到的key前截断
63 psec = strchr(psec,']') +1; //当前节点之后开始找
64 while((psec=strchr(psec,'[')) != NULL){
65 //判断该行是否是注释
66 char* pt = psec++; //psec指向'['的下一个去
67 while(*(--pt) != ';'&& *pt != '\n');
68 if(*pt == ';'){ continue;}//是注释,下一个
69 //不是注释,判断是否是合法节点([]存在,有内容且在同一行)
70 pt = psec;
71 while(*(++pt) != ']' && *pt != '\n');
72 if(*pt==']'){//当前行有']'来闭合,说明Section和Key之间还有节点
73 pval = NULL; //设置为NULL,表示不用找了
74 break;
75 }
76 }//end while
77 if(pval == NULL){
78 break; //找到的key不是传入Section下的
79 }
80
81 //确定了找到的key确实与传入的一致,查找value位置
82 while(*pval != '=' && *pval != '\n' && *pval != '\0'){
83 ++pval; //查找'='的位置(key=value必须在一行)
84 }
85 if(*pval != '='){break;} //没有找到value
86 ++pval; //现在pkey指向value(可能用空白,使用sscanf来去除)
87 // 找到 value 的情况,仅此一处
88 if((fsize - (pval - buf) - nSize) > 0){
89 pval[nSize-1] = '\0'; //避免value太长
90 }
91 len = sscanf(pval,"%s",ReturnedString); //sscanf %s 遇到空格\n\t\0都结束
92 free(buf); //释放buf
93 return len; //返回拷贝的长度
94
95 //结束查找
96 }while(0);
97
98 //没有找到的情况
99 strncpy(ReturnedString,Default,nSize-1);
100 ReturnedString[nSize-1] = '\0';
101 free(buf); //释放buf
102 return strlen(ReturnedString);
103 }
GetPrivateProfileInt从INI文件中读取Int值
1 /*函数说明:从FileName指定的ini文件中读取section节点下key键对应的value值(整型数)GetPrivateProfileInt
2 *参数说明: Section: 节点名(不区分大小写)
3 * Key: 键名(不区分大小写)
4 * Default: 没有找到对应的value时的默认值
5 * FileName: ini文件路径
6 *返回值:读取成功返回找到的value值。没找到就返回Default
7 */
8
9 int GetPrivateProfileInt(
10 const char* Section, // 指向包含 Section 名称的字符串地址
11 const char* Key, // 指向包含 Key 名称的字符串地址
12 int Default, // 如果 Key 值没有找到,则返回缺省的值是多少
13 const char* FileName // ini 文件的文件名
14 )
15 {
16 char buf[1024];
17 sprintf(&buf[512],"%d",Default); //获取默认值
18 GetPrivateProfileString(Section,Key,&buf[512],buf,512,FileName);
19 return atoi(buf);
20 }