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

2022年01月15日 阅读数:4
这篇文章主要向大家介绍用C语言实现解析简单配置文件的小工具,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。


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

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


[plain] ​​view plain​​​​copy​​  函数


  1. ;资源管理器配置脚本  

  2. ;以行为单位,每行不能超过255个字符  
  3. ;空行和以;开头的注释行会被忽略掉  
  4. ;每行都关联一个资源文件,资源序号从0开始,依次递增  

  5. .\img\img128x128.bin  
  6. .\snd\start.wav  
  7. .\img\sheis1.bin  
  8. .\snd\balloon.wav  
  9. .\img\sheis2.bin  


工具的源代码贴在这里:工具


[cpp] ​​view plain​​​​copy​​  spa


  1. #include <ctype.h>  
  2. #include <string.h>  
  3. #include <stdlib.h>  
  4. #include <stdio.h>  

  5. /* 定义相关文件名 */  
  6. #define CONFIG_FILE_NAME        ("config.txt")  
  7. #define RESPAK_FILE_NAME        ("resmm.bin")  
  8. #define ADDRS_C_FILE_NAME       ("resmm_addrs.c")  

  9. /* 定义配置行最大的字符数 */  
  10. #define LINE_CHARS      (255)  
  11. /* 定义复制文件数据时的缓冲区大小 */  
  12. #define BUF_SIZE        (8 * 1024)  

  13. /* 从配置行提取文件名 */  
  14. static char* extract_file_name(const char* line, char* file_name)  
  15. {  
  16.     /* 过滤配置行左边的空格符 */  
  17.     while(isspace(*line++)){};  
  18.     line--;  
  19.     /* 忽略空行和注释行 */  
  20.     if((*line == '\0') || (*line == ';'))  
  21.         return NULL;  

  22.     /* 提取文件名,并去掉右边的空格符 */  
  23.     strcpy(file_name, line);  
  24.     {  
  25.         char* p = file_name + strlen(file_name) - 1;  
  26.         while(isspace(*p--)){};  
  27.         p++;  
  28.         p++;  
  29.         *p = '\0';  
  30.     }  

  31.     return file_name;  
  32. }  

  33. /* 扫描有效文件数 */  
  34. static int scan_file_count(FILE* cf)  
  35. {  
  36.     char line[LINE_CHARS + 1];  
  37.     char file_name[LINE_CHARS + 1];  
  38.     int count = 0;  

  39.     while(!feof(cf))  
  40.     {  
  41.         fgets(line, LINE_CHARS, cf);  
  42.         if(extract_file_name(line, file_name) != NULL)  
  43.             count++;  
  44.     }  

  45.     return count;  
  46. }  

  47. /* 复制文件数据 */  
  48. static size_t copy_file_datas(FILE* pf, FILE* rf)  
  49. {  
  50.     unsigned char buf[BUF_SIZE];  
  51.     size_t total = 0;  
  52.     size_t len;  

  53.     do{  
  54.         len = fread(buf, sizeof(unsigned char), BUF_SIZE, rf);  
  55.         fwrite(buf, sizeof(unsigned char), len, pf);  
  56.         total += len;  
  57.     }while(len == BUF_SIZE);  

  58.     return total;  
  59. }  

  60. /* 主函数 */  
  61. int main(int argc, char* argv[])  
  62. {  
  63.     FILE* cf;  
  64.     FILE* pf;  
  65.     FILE* rf;  
  66.     int count;  
  67.     size_t* lens;  
  68.     size_t len;  
  69.     unsigned int addr;  
  70.     char line[LINE_CHARS + 1];  
  71.     char file_name[LINE_CHARS + 1];  
  72.     int i;  

  73.     /* 打开配置文件,并扫描有效文件数 */  
  74.     if((cf = fopen(CONFIG_FILE_NAME, "rt")) == NULL)  
  75.     {  
  76.         printf("Can\'t open %s!\n", CONFIG_FILE_NAME);  
  77.         return -1;  
  78.     }  
  79.     count = scan_file_count(cf);  
  80.     fseek(cf, 0L, SEEK_SET);  

  81.     /* 打开资源包文件 */  
  82.     if((pf = fopen(RESPAK_FILE_NAME, "wb")) == NULL)  
  83.     {  
  84.         printf("Can\'t create %s!\n", RESPAK_FILE_NAME);  
  85.         fclose(cf);  
  86.         return -1;  
  87.     }  

  88.     /* 复制打包资源文件,并统计其大小 */  
  89.     if((lens = (size_t*)malloc(sizeof(size_t) * count)) == NULL)  
  90.     {  
  91.         printf("No enough memory!\n");  
  92.         fclose(pf);  
  93.         fclose(cf);  
  94.         return -1;  
  95.     }  
  96.     i = 0;  
  97.     while(!feof(cf))  
  98.     {  
  99.         fgets(line, LINE_CHARS, cf);  
  100.         if(extract_file_name(line, file_name) != NULL)  
  101.         {  
  102.             if((rf = fopen(file_name, "rb")) == NULL)  
  103.             {  
  104.                 printf("Can\'t open %s!\n", file_name);  
  105.                 fclose(pf);  
  106.                 fclose(cf);  
  107.                 return -1;  
  108.             }  
  109.             if((len = copy_file_datas(pf, rf)) == 0)  
  110.             {  
  111.                 printf("File %s is empty!\n", file_name);  
  112.                 fclose(pf);  
  113.                 fclose(cf);  
  114.                 return -1;  
  115.             }  
  116.             lens[i++] = len;  
  117.             fclose(rf);  
  118.         }  
  119.     }  
  120.     fclose(pf);  
  121.     fclose(cf);  

  122.     /* 打开地址描述的C语言源文件 */  
  123.     if((cf = fopen(ADDRS_C_FILE_NAME, "wt")) == NULL)  
  124.     {  
  125.         printf("Can\'t open %s!\n", ADDRS_C_FILE_NAME);  
  126.         return -1;  
  127.     }  

  128.     /* 把各个资源的地址和长度信息写入C语言数组 */  
  129.     fprintf(cf, "#define RES_COUNT\t(%d)\n\n", count);  
  130.     fprintf(cf, "static const INT32U addrs[RES_COUNT] = \n{\n");  
  131.     addr = 0;  
  132.     for(i = 0; i < count; i++)  
  133.     {  
  134.         fprintf(cf, "\t\t0x%08x,\n", addr);  
  135.         addr += lens[i];  
  136.     }  
  137.     fprintf(cf, "};\n\n");  
  138.     fprintf(cf, "static const INT32U lens[RES_COUNT] = \n{\n");  
  139.     for(i = 0; i < count; i++)  
  140.         fprintf(cf, "\t\t0x%08x,\n", lens[i]);  
  141.     fprintf(cf, "};");  

  142.     fclose(cf);  
  143.     free(lens);  
  144.     return 0;  
  145. }  


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




[cpp] ​​view plain​​​​copy​​  字符串


  1. #define RES_COUNT   (5)  

  2. static const INT32U addrs[RES_COUNT] =   
  3. {  
  4.         0x00000000,  
  5.         0x00008000,  
  6.         0x0000889a,  
  7.         0x0001089a,  
  8.         0x0001219a,  
  9. };  

  10. static const INT32U lens[RES_COUNT] =   
  11. {  
  12.         0x00008000,  
  13.         0x0000089a,  
  14.         0x00008000,  
  15.         0x00001900,  
  16.         0x00008000,  
  17. };  


root get