06 | C语言模拟配置文件的读取和加解密


目的

读出类似这样的配置文件

abc:abc

并且对文件进行一个简单的加密操作

注意的点

  1. 配置信息结构体key和value要自己设定,这不是在python中
  2. 对于C语言中动态内存分配记得要提供“一个返回有效行数的函数”

config.h

#include 
#include 
#include 

//配置信息结构体
struct ConfigInfo
{
	char key[64];
	char value[64];
};

//获取有效行数
int getFileLines(const char *filePath);

//检测当前行是否有效信息
int isValidLines(const char* str);

//解析文件
void parseFile(const char *filePath,int lines,struct ConfigInfo ** configinfo);

//根据key获取对应的value
char* getInfoByKey(const char * key, struct ConfigInfo * configinfo,int len);

//释放内存
void freeConfigInfo(struct ConfigInfo* configinfo);

config.c

#include "config.h"

int getFileLines(const char *filePath) 
{
	FILE *file=fopen(filePath, "r");
	if (file == NULL) {
		return -1;
	}
	char buf[1024] = { 0 };
	int lines=0;
	while (fgets(buf, 1024, file) != NULL)
	{
		if (isValidLines(buf))
		{
			lines++;
		}
		memset(buf, 0, 1024);
	}
	return lines;
	fclose(file);
}

int isValidLines(const char* str)
{
	if (strchr(str, ':') == NULL)
	{
		return 0;//返回假代表无效行
	}
	return 1;
}

void parseFile(const char *filePath, int lines, struct ConfigInfo ** configinfo)
{
	struct ConfigInfo *info=(ConfigInfo *)malloc(sizeof(struct ConfigInfo)*lines);
	if (info == NULL)
	{
		return;
	}
	FILE * file = fopen(filePath, "r");
	if (file == NULL) {
		return;
	}
	char buf[1024] = { 0 };
	int index = 0;
	while (fgets(buf, 1024, file) != NULL)
	{
		if (isValidLines(buf))
		{
			//有效信息才去解析
			//清空key和value数组
			memset(info[index].key, 0, 64);
			memset(info[index].value, 0, 64);
			char * pos = strchr(buf, ':');
			strncpy(info[index].key, buf, pos - buf);
			strncpy(info[index].value, pos+1, strlen(pos+1)-1); //减一是为了丢掉字符串最后换行符
			index++;
		}
		memset(buf, 0, 1024);
	}
	*configinfo = info;
}

char* getInfoByKey(const char * key, struct ConfigInfo * configinfo, int len)
{
	for (int i = 0; i < len; i++) {
		if (strcmp(key, configinfo[i].key) == 0)
		{
			return configinfo[i].value;
		}
	}
}

//释放内存
void freeConfigInfo(struct ConfigInfo* configinfo)
{
	if (configinfo != NULL)
	{
		free(configinfo);
		configinfo = NULL;
	}
}

code.h

#include 
#include 
#include 
//文件加密
void codeFile(const char *sourceFilePath, const char *destFilePath);
//解密文件
void decodeFile(const char *sourceFilePath, const char *destFilePath);

code.c

#include "code.h"

void codeFile(const char *sourceFilePath, const char *destFilePath)
{
	srand((unsigned int)time(NULL));
	FILE *fp1 = fopen(sourceFilePath, "r");
	FILE *fp2 = fopen(destFilePath, "w");

	if (!fp1 || !fp2) {
		printf("文件打开失败\n");
		return;
	}
	char ch;
	//读字符的标准写法
	while ((ch = fgetc(fp1)) != EOF) {
		//全部调整为偶数		
		//0000 0000 0010 0011  <<4
		//0000 0010 0011 0000
		short temp = (short)ch;
		temp = temp << 4;
		//全部调整为负数
		//0000 0000 0011 0000 |
		//1000 0000 0000 0000
		//1000 0000 0011 0000
		temp = temp | 0x8000;
		//加一个数字,有奇数有偶数
		//1000 0000 0011 0000 + 0000~1111
		temp += rand() % 16;
		fprintf(fp2, "%hd", temp);
	}
	fclose(fp1);
	fclose(fp2);
}

//解密文件
void decodeFile(const char *sourceFilePath, const char *destFilePath)
{
	FILE *fp1 = fopen(sourceFilePath, "r");
	FILE *fp2 = fopen(destFilePath, "w");

	if (!fp1 || !fp2) {
		printf("文件打开失败\n");
		return;
	}
	//去掉最高位,去掉底五位的无效位
	//1000 0000 0011 1010 <<1
	//000 0000 0011 10100 >>5
	short temp;

	while (!feof(fp1))
	{
		fscanf(fp1, "%hd", &temp);
		temp = temp << 1;
		temp = temp >> 5;
		char ch = (char)temp;
		fputc(ch, fp2);
	}
	fclose(fp1);
	fclose(fp2);
}

使用


#include "config.h"
#include 
#include 
#include 
#include "code.h"
int main_6() {
	const char *filePath = "./config.txt";

	int len = getFileLines(filePath);
	printf("文件的有效行数为:%d\n", len);

	struct ConfigInfo *configInfo = NULL;
	parseFile(filePath, len, &configInfo);
	//测试根据key获取value
	printf("heroid=%s\n", getInfoByKey("heroid", configInfo, len));
	printf("herowe=%s\n", getInfoByKey("herowe", configInfo, len));
	//释放空间
	freeConfigInfo(configInfo);
	configInfo = NULL;

	//文件加密
	codeFile("./config.txt", "./加密文件.txt");
	//文件解密
	decodeFile("./加密文件.txt", "./解密文件.txt");
	getchar();
	return 0;
}