用C语言实现解析简单配置文件的小工具

本文介绍作者写的一个小工具,简单的代码中包含了C语言对字符串的处理技巧,对文本文件的简单解析,二进制文件的数据复制的方法,以及格式化输出文本文件的示例。

工具的输入是如下内容的配置文件:

 

[plain] view plaincopy
 
  1. ;资源管理器配置脚本  
  2.   
  3. ;以行为单位,每行不能超过255个字符  
  4. ;空行和以;开头的注释行会被忽略掉  
  5. ;每行都关联一个资源文件,资源序号从0开始,依次递增  
  6.   
  7. .\img\img128x128.bin  
  8. .\snd\start.wav  
  9. .\img\sheis1.bin  
  10. .\snd\balloon.wav  
  11. .\img\sheis2.bin  

工具的源代码贴在这里:

 

[cpp] view plaincopy
 
  1. #include <ctype.h>  
  2. #include <string.h>  
  3. #include <stdlib.h>  
  4. #include <stdio.h>  
  5.   
  6. /* 定义相关文件名 */  
  7. #define CONFIG_FILE_NAME        ("config.txt")  
  8. #define RESPAK_FILE_NAME        ("resmm.bin")  
  9. #define ADDRS_C_FILE_NAME       ("resmm_addrs.c")  
  10.   
  11. /* 定义配置行最大的字符数 */  
  12. #define LINE_CHARS      (255)  
  13. /* 定义复制文件数据时的缓冲区大小 */  
  14. #define BUF_SIZE        (8 * 1024)  
  15.   
  16. /* 从配置行提取文件名 */  
  17. static char* extract_file_name(const char* line, char* file_name)  
  18. {  
  19.     /* 过滤配置行左边的空格符 */  
  20.     while(isspace(*line++)){};  
  21.     line--;  
  22.     /* 忽略空行和注释行 */  
  23.     if((*line == '\0') || (*line == ';'))  
  24.         return NULL;  
  25.   
  26.     /* 提取文件名,并去掉右边的空格符 */  
  27.     strcpy(file_name, line);  
  28.     {  
  29.         char* p = file_name + strlen(file_name) - 1;  
  30.         while(isspace(*p--)){};  
  31.         p++;  
  32.         p++;  
  33.         *p = '\0';  
  34.     }  
  35.   
  36.     return file_name;  
  37. }  
  38.   
  39. /* 扫描有效文件数 */  
  40. static int scan_file_count(FILE* cf)  
  41. {  
  42.     char line[LINE_CHARS + 1];  
  43.     char file_name[LINE_CHARS + 1];  
  44.     int count = 0;  
  45.   
  46.     while(!feof(cf))  
  47.     {  
  48.         fgets(line, LINE_CHARS, cf);  
  49.         if(extract_file_name(line, file_name) != NULL)  
  50.             count++;  
  51.     }  
  52.   
  53.     return count;  
  54. }  
  55.   
  56. /* 复制文件数据 */  
  57. static size_t copy_file_datas(FILE* pf, FILE* rf)  
  58. {  
  59.     unsigned char buf[BUF_SIZE];  
  60.     size_t total = 0;  
  61.     size_t len;  
  62.   
  63.     do{  
  64.         len = fread(buf, sizeof(unsigned char), BUF_SIZE, rf);  
  65.         fwrite(buf, sizeof(unsigned char), len, pf);  
  66.         total += len;  
  67.     }while(len == BUF_SIZE);  
  68.   
  69.     return total;  
  70. }  
  71.   
  72. /* 主函数 */  
  73. int main(int argc, char* argv[])  
  74. {  
  75.     FILE* cf;  
  76.     FILE* pf;  
  77.     FILE* rf;  
  78.     int count;  
  79.     size_t* lens;  
  80.     size_t len;  
  81.     unsigned int addr;  
  82.     char line[LINE_CHARS + 1];  
  83.     char file_name[LINE_CHARS + 1];  
  84.     int i;  
  85.   
  86.     /* 打开配置文件,并扫描有效文件数 */  
  87.     if((cf = fopen(CONFIG_FILE_NAME, "rt")) == NULL)  
  88.     {  
  89.         printf("Can\'t open %s!\n", CONFIG_FILE_NAME);  
  90.         return -1;  
  91.     }  
  92.     count = scan_file_count(cf);  
  93.     fseek(cf, 0L, SEEK_SET);  
  94.   
  95.     /* 打开资源包文件 */  
  96.     if((pf = fopen(RESPAK_FILE_NAME, "wb")) == NULL)  
  97.     {  
  98.         printf("Can\'t create %s!\n", RESPAK_FILE_NAME);  
  99.         fclose(cf);  
  100.         return -1;  
  101.     }  
  102.   
  103.     /* 复制打包资源文件,并统计其大小 */  
  104.     if((lens = (size_t*)malloc(sizeof(size_t) * count)) == NULL)  
  105.     {  
  106.         printf("No enough memory!\n");  
  107.         fclose(pf);  
  108.         fclose(cf);  
  109.         return -1;  
  110.     }  
  111.     i = 0;  
  112.     while(!feof(cf))  
  113.     {  
  114.         fgets(line, LINE_CHARS, cf);  
  115.         if(extract_file_name(line, file_name) != NULL)  
  116.         {  
  117.             if((rf = fopen(file_name, "rb")) == NULL)  
  118.             {  
  119.                 printf("Can\'t open %s!\n", file_name);  
  120.                 fclose(pf);  
  121.                 fclose(cf);  
  122.                 return -1;  
  123.             }  
  124.             if((len = copy_file_datas(pf, rf)) == 0)  
  125.             {  
  126.                 printf("File %s is empty!\n", file_name);  
  127.                 fclose(pf);  
  128.                 fclose(cf);  
  129.                 return -1;  
  130.             }  
  131.             lens[i++] = len;  
  132.             fclose(rf);  
  133.         }  
  134.     }  
  135.     fclose(pf);  
  136.     fclose(cf);  
  137.   
  138.     /* 打开地址描述的C语言源文件 */  
  139.     if((cf = fopen(ADDRS_C_FILE_NAME, "wt")) == NULL)  
  140.     {  
  141.         printf("Can\'t open %s!\n", ADDRS_C_FILE_NAME);  
  142.         return -1;  
  143.     }  
  144.   
  145.     /* 把各个资源的地址和长度信息写入C语言数组 */  
  146.     fprintf(cf, "#define RES_COUNT\t(%d)\n\n", count);  
  147.     fprintf(cf, "static const INT32U addrs[RES_COUNT] = \n{\n");  
  148.     addr = 0;  
  149.     for(i = 0; i < count; i++)  
  150.     {  
  151.         fprintf(cf, "\t\t0x%08x,\n", addr);  
  152.         addr += lens[i];  
  153.     }  
  154.     fprintf(cf, "};\n\n");  
  155.     fprintf(cf, "static const INT32U lens[RES_COUNT] = \n{\n");  
  156.     for(i = 0; i < count; i++)  
  157.         fprintf(cf, "\t\t0x%08x,\n", lens[i]);  
  158.     fprintf(cf, "};");  
  159.   
  160.     fclose(cf);  
  161.     free(lens);  
  162.     return 0;  
  163. }  

格式化输出的文本文件是这样的:

 

 

 

[cpp] view plaincopy
 
  1. #define RES_COUNT   (5)  
  2.   
  3. static const INT32U addrs[RES_COUNT] =   
  4. {  
  5.         0x00000000,  
  6.         0x00008000,  
  7.         0x0000889a,  
  8.         0x0001089a,  
  9.         0x0001219a,  
  10. };  
  11.   
  12. static const INT32U lens[RES_COUNT] =   
  13. {  
  14.         0x00008000,  
  15.         0x0000089a,  
  16.         0x00008000,  
  17.         0x00001900,  
  18.         0x00008000,  
  19. };  
posted @ 2013-12-22 21:49  midu  阅读(792)  评论(0编辑  收藏  举报