您的位置:首页 > 编程语言 > C语言/C++

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

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

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

[plain] view plaincopy

;资源管理器配置脚本

;以行为单位,每行不能超过255个字符

;空行和以;开头的注释行会被忽略掉

;每行都关联一个资源文件,资源序号从0开始,依次递增

.\img\img128x128.bin

.\snd\start.wav

.\img\sheis1.bin

.\snd\balloon.wav

.\img\sheis2.bin

工具的源代码贴在这里:

[cpp] view plaincopy

#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;

}

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

[cpp] view plaincopy

#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,

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: