用C语言实现解析简单配置文件的小工具
本文介绍作者写的一个小工具,简单的代码中包含了C语言对字符串的处理技巧,对文本文件的简单解析,二进制文件的数据复制的方法,以及格式化输出文本文件的示例。
工具的输入是如下内容的配置文件:
- ;资源管理器配置脚本
- ;以行为单位,每行不能超过255个字符
- ;空行和以;开头的注释行会被忽略掉
- ;每行都关联一个资源文件,资源序号从0开始,依次递增
- .\img\img128x128.bin
- .\snd\start.wav
- .\img\sheis1.bin
- .\snd\balloon.wav
- .\img\sheis2.bin
工具的源代码贴在这里:
- #include <ctype.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- /* 定义相关文件名 */
- #define CONFIG_FILE_NAME ("config.txt")
- #define RESPAK_FILE_NAME ("resmm.bin")
- #define ADDRS_C_FILE_NAME ("resmm_addrs.c")
- /* 定义配置行最大的字符数 */
- #define LINE_CHARS (255)
- /* 定义复制文件数据时的缓冲区大小 */
- #define BUF_SIZE (8 * 1024)
- /* 从配置行提取文件名 */
- static char* extract_file_name(const char* line, char* file_name)
- {
- /* 过滤配置行左边的空格符 */
- while(isspace(*line++)){};
- line--;
- /* 忽略空行和注释行 */
- if((*line == '\0') || (*line == ';'))
- return NULL;
- /* 提取文件名,并去掉右边的空格符 */
- strcpy(file_name, line);
- {
- char* p = file_name + strlen(file_name) - 1;
- while(isspace(*p--)){};
- p++;
- p++;
- *p = '\0';
- }
- return file_name;
- }
- /* 扫描有效文件数 */
- static int scan_file_count(FILE* cf)
- {
- char line[LINE_CHARS + 1];
- char file_name[LINE_CHARS + 1];
- int count = 0;
- while(!feof(cf))
- {
- fgets(line, LINE_CHARS, cf);
- if(extract_file_name(line, file_name) != NULL)
- count++;
- }
- return count;
- }
- /* 复制文件数据 */
- static size_t copy_file_datas(FILE* pf, FILE* rf)
- {
- unsigned char buf[BUF_SIZE];
- size_t total = 0;
- size_t len;
- do{
- len = fread(buf, sizeof(unsigned char), BUF_SIZE, rf);
- fwrite(buf, sizeof(unsigned char), len, pf);
- total += len;
- }while(len == BUF_SIZE);
- return total;
- }
- /* 主函数 */
- int main(int argc, char* argv[])
- {
- FILE* cf;
- FILE* pf;
- FILE* rf;
- int count;
- size_t* lens;
- size_t len;
- unsigned int addr;
- char line[LINE_CHARS + 1];
- char file_name[LINE_CHARS + 1];
- int i;
- /* 打开配置文件,并扫描有效文件数 */
- if((cf = fopen(CONFIG_FILE_NAME, "rt")) == NULL)
- {
- printf("Can\'t open %s!\n", CONFIG_FILE_NAME);
- return -1;
- }
- count = scan_file_count(cf);
- fseek(cf, 0L, SEEK_SET);
- /* 打开资源包文件 */
- if((pf = fopen(RESPAK_FILE_NAME, "wb")) == NULL)
- {
- printf("Can\'t create %s!\n", RESPAK_FILE_NAME);
- fclose(cf);
- return -1;
- }
- /* 复制打包资源文件,并统计其大小 */
- if((lens = (size_t*)malloc(sizeof(size_t) * count)) == NULL)
- {
- printf("No enough memory!\n");
- fclose(pf);
- fclose(cf);
- return -1;
- }
- i = 0;
- while(!feof(cf))
- {
- fgets(line, LINE_CHARS, cf);
- if(extract_file_name(line, file_name) != NULL)
- {
- if((rf = fopen(file_name, "rb")) == NULL)
- {
- printf("Can\'t open %s!\n", file_name);
- fclose(pf);
- fclose(cf);
- return -1;
- }
- if((len = copy_file_datas(pf, rf)) == 0)
- {
- printf("File %s is empty!\n", file_name);
- fclose(pf);
- fclose(cf);
- return -1;
- }
- lens[i++] = len;
- fclose(rf);
- }
- }
- fclose(pf);
- fclose(cf);
- /* 打开地址描述的C语言源文件 */
- if((cf = fopen(ADDRS_C_FILE_NAME, "wt")) == NULL)
- {
- printf("Can\'t open %s!\n", ADDRS_C_FILE_NAME);
- return -1;
- }
- /* 把各个资源的地址和长度信息写入C语言数组 */
- fprintf(cf, "#define RES_COUNT\t(%d)\n\n", count);
- fprintf(cf, "static const INT32U addrs[RES_COUNT] = \n{\n");
- addr = 0;
- for(i = 0; i < count; i++)
- {
- fprintf(cf, "\t\t0x%08x,\n", addr);
- addr += lens[i];
- }
- fprintf(cf, "};\n\n");
- fprintf(cf, "static const INT32U lens[RES_COUNT] = \n{\n");
- for(i = 0; i < count; i++)
- fprintf(cf, "\t\t0x%08x,\n", lens[i]);
- fprintf(cf, "};");
- fclose(cf);
- free(lens);
- return 0;
- }
格式化输出的文本文件是这样的:
- #define RES_COUNT (5)
- static const INT32U addrs[RES_COUNT] =
- {
- 0x00000000,
- 0x00008000,
- 0x0000889a,
- 0x0001089a,
- 0x0001219a,
- };
- static const INT32U lens[RES_COUNT] =
- {
- 0x00008000,
- 0x0000089a,
- 0x00008000,
- 0x00001900,
- 0x00008000,
- };
用C语言实现解析简单配置文件的小工具的更多相关文章
- marked插件在线实时解析markdown的web小工具
访问地址: https://mdrush.herokuapp.com/ github项目: https://github.com/qcer/MDRush 实现简介: 1.动态数据绑定 借助Vuejs, ...
- 简单的mongo小工具 python
#!/bin/python #coding=utf-8 ### eg : mgotool.py -i 127.0.0.1 -p 10001 -a xxxxx -u root -rc #import s ...
- R语言:用简单的文本处理方法优化我们的读书体验
博客总目录:http://www.cnblogs.com/weibaar/p/4507801.html 前言 延续之前的用R语言读琅琊榜小说,继续讲一下利用R语言做一些简单的文本处理.分词的事情.其实 ...
- [C语言]声明解析器cdecl修改版
一.写在前面 K&R曾经在书中承认,"C语言声明的语法有时会带来严重的问题.".由于历史原因(BCPL语言只有唯一一个类型——二进制字),C语言声明的语法在各种合理的组合下 ...
- 踢爆IT劣书出版黑幕——由清华大学出版社之《C语言入门很简单》想到的(1)
1.前言与作者 首先声明,我是由于非常偶然的机会获得<C语言入门很简单>这本书的,绝对不是买的.买这种书实在丢不起那人. 去年这书刚出版时,在CU论坛举行试读推广,我当时随口说了几句(没说 ...
- 留念 C语言第一课简单的计算器制作
留念 C语言第一课简单的计算器制作 学C语言这么久了. /* 留念 C语言第一课简单的计算器制作 */ #include<stdio.h> #include<stdlib.h ...
- 用C语言编写一个简单的词法分析程序
问题描述: 用C或C++语言编写一个简单的词法分析程序,扫描C语言小子集的源程序,根据给定的词法规则,识别单词,填写相应的表.如果产生词法错误,则显示错误信息.位置,并试图从错误中恢复.简单的恢复方法 ...
- 用Go语言实现一个简单的聊天机器人
一.介绍 目的:使用Go语言写一个简单的聊天机器人,复习整合Go语言的语法和基础知识. 软件环境:Go1.9,Goland 2018.1.5. 二.回顾 Go语言基本构成要素:标识符.关键字.字面量. ...
- Spring中 <context:property-placeholder 的使用与解析 .properties 配置文件的加载
转: Spring中property-placeholder的使用与解析 Spring中property-placeholder的使用与解析 我们在基于spring开发应用的时候,一般都会将数据库的配 ...
随机推荐
- WinForm开发,窗体显示和窗体传值相关知识总结
主窗体中代码: public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void b ...
- Perl的新特性开启
1.perl自从5.8开始,新特性需要开启才可以使用,默认只是5.8版本,而不管当前你使用的是那个版本. 2.开启新特性,当然最高可用版本是你实际安装的版本,假设你安装的是v5.26版 ; #或者这样 ...
- 【Anroid】9.1 ListView相关类及其适配器
分类:C#.Android.VS2015: 创建日期:2016-02-18 一.简介 列表视图(ListView)是Android应用程序中使用最频繁的UI组件,从无处不在短菜单选项列表到冗长的联系人 ...
- 2>/dev/null
2>/dev/null是如果你的命今出错的话,错误报告直接输出到黑洞里不会显示在屏幕上. ls -al 1>list.txt 2>list.err #将显示的数据,正确的输出到lis ...
- CCCallFunc和CCSequence
class CC_DLL CCCallFunc : public CCActionInstant //<NSCopying> void Issue1305_2::onEnter() { A ...
- python学习之pyc,pyo,pyd文件
pyc:二进制文件,python文件经过编译器编译之后的文件.可以提高文件加载速度. pyo:二进制文件,优化编译后的文件.可以通过`python -O file.py`生成. pyd:python的 ...
- VC中的树形控件
树形控件可以显示出各项之间的层次关系,因此在VC中很常用. 1.树形控件的常用风格 TVS_HASBUTTONS 在父项目前显示+.-.用户可以通过点击该符号来打开或收起子项 TVS_HASLINES ...
- 寻找最大的k个数问题
这是编程之美书第2.5节的一道题目. 各种解法: 解法一,用nlgn复杂度的排序算法对数组进行从大到小排序,取前K个.但这方法做了两件不必要做的事:它对想得到的K个数进行了排序,对不想得到的n-K个数 ...
- dubbox2.8.4例子教程一
简介 Dubbo是一个来自阿里巴巴的开源分布式服务框架,当当根据自身的需求,为Dubbo实现了一些新的功能,包括REST风格远程调用.Kryo/FST序列化等等.并将其命名为Dubbox(即Dubbo ...
- 设置DatagridView的列头样式
设置DataGridView.ColumnHeaderDefaultCellStyle的BackColor属性会发现没有效果.这是因为在启动了可视样式的时候,BackColor和ForeColor的值 ...