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

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

  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

工具的源代码贴在这里:

  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. }

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

  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. };

最新文章

  1. Android无需申请权限拨打电话
  2. 5种 JavaScript 调用函数的方法
  3. WPF菜单
  4. vs2015 现用插件
  5. Hadoop 基准测试与example
  6. 检测局域网中还可用的ip地址
  7. OSG中的示例程序简介(转)
  8. ftp一些东东
  9. leetcode dfs Validate Binary Search Tree
  10. 前端里移动端到底比pc端多哪些知识?
  11. python基础(六)dict字典和文件操作open
  12. MyCat 入门:漫谈 MyCat 配置系统
  13. 英语词汇(2)fall down,fall off和fall over
  14. 微信小程序-参数传递与事件处理
  15. RDIFramework.NET V3.3 WinForm版角色授权管理新增角色对操作权限项、模块起止生效日期的设置
  16. redis跳跃表
  17. 1195: [HNOI2006]最短母串
  18. 字符集不同导致的ORA-00972
  19. nfs 客户端启动报错rpc.mountd: svc_tli_create: could not open connection for tcp6
  20. CentOS搭建NFS服务

热门文章

  1. STM32以太网ETH
  2. spineRunTime for cocos2dx v3 中动画播完删除animation
  3. Android开发9——Activity的启动模式
  4. dubbo-admin 管理台的部署
  5. [Docker] Docker Hub加速
  6. 黑客编程教程(十三)多线程DOS程序
  7. TagsView.vue
  8. Activiti初学者教程 (zhuan)
  9. js异步加载的解决方案
  10. jquery ajax异步提交表单数据的方法