文件处理小程序(包含哈夫曼文件压缩-解压等 C语言)

文末有源代码

文件压缩、解压、加密(异或加密)、解密功能等都实现了,但是处理后文件命名有点不合理,采用了加前缀的方法得到处理后的文件名,应该是改变后缀名。

应该这种更好:test.txt --- >> 压缩---->> test.myzip  


演示:

文件处理小程序(包含哈夫曼文件压缩-解压等 C语言)_第1张图片

 测试文本:

文件处理小程序(包含哈夫曼文件压缩-解压等 C语言)_第2张图片

 

  压缩率有点低,百思不得其解。。。

文件处理小程序(包含哈夫曼文件压缩-解压等 C语言)_第3张图片

 

 

 解压 压缩后的文本文件看是否正确,不乱码:

文件处理小程序(包含哈夫曼文件压缩-解压等 C语言)_第4张图片

 

可以看出解压正常:

​​​​​​​文件处理小程序(包含哈夫曼文件压缩-解压等 C语言)_第5张图片

 

 其余还有加密等操作,就不一一演示了。

源代码直接运行即可

源代码:

#include
#include
#include
#include//调用GetCurrentDirectory()获得路径,以便删除文件
#include //调用clock函数计算运行时间 
#define PART_LEN 10000//文件加密的最长长度
#define FILE_NAME_MAX_LEN 80//文件名称最大的长度
#define KEY_LEN 15
const char file_start[] = "MyZip_";
char file_path[110];

unsigned long file_len = 0;
int char_kinds = 0;
int USER_CT = 1000;

typedef struct Ad
{
	int Id;
	char Key[20];
	struct Ad* next;
}Admi;
Admi *tail = NULL;//保存账号信息的尾节点

//哈夫曼树节点
typedef struct
{
	int ch;
	unsigned long count;//压缩时记录字符频度,解压时记录字符编码长度
	char bits[256];//字符对应的哈夫曼编码,最多255个节点 
	int lch, rch, parent;//存放下标,利用指针数组
}HufNode, * HufTree;

HufNode huf_tree[512], tmp;//定义为全局变量,使用前初始化,调用函数



//一级函数
void menu1();//一级页面 
void menu2();//二级页面 
void CreateAd(Admi**head);//创建账号
void Login(Admi* head);//登录 

void to_compress();//文件压缩
void to_extract();//文件解压
void to_Encrypted();//加密函数
void to_Unencrypted();//解密函数
void to_copy();//文件复制
void to_delete();//文件删除
void to_cut();//文件剪切

//二级函数:
void get_account(int* account);//自动生成账号,以确保唯一性
void saveAd(Admi* head);//储存账号信息
Admi* getAd();//读取账号信息
void operation();//二级页面,文件操作选项

void InitHafNode();//初始化哈夫曼节点
float compress(const char* file_name, const char* com_file_name);//压缩文件
int extract(const char* file_name, const  char* ex_file_name);//解压文件

int copy_file(char* file_name, char* copy_file_name);//复制文件
void cut_name(const char* file_name, char* only_name);//截取文件名称,去除后缀
void cut_end_name(const char* file_name, char* end_name);//截取文件名的后缀
int Encrypted(const char* file_name, const char* encry_file_name);//加密
int Unencrypted(const char* file_name, const char* unencry_file_name, const char* password);//解密

//-----------------------函数实现区--------------------------------------

//一级函数区
void menu2()
{
	printf("-----------欢迎使用文件处理小软件!----------\n\n");
	printf("               1.压缩文件\n\n");
	printf("               2.解压文件\n\n");
	printf("               3.加密文件\n\n");
	printf("               4.解密文件\n\n");
	printf("               5.删除文件\n\n");
	printf("               6.复制文件\n\n");
	printf("               7.剪切文件\n\n");
	printf("               8.返回上一级\n");

}

void menu1()
{
	printf("-----------欢迎使用文件处理小软件!----------\n\n");
	printf("               1.创建管理员账号\n\n");
	printf("               2.登录账号\n\n");
	printf("               3.退出程序\n\n");
}


void CreateAd(Admi** head)//创建账号
{
	int account;
	char key[12], tmp[12];
	get_account(&account);
	printf("您的账号为:%d", account);
	printf("请输入您的密码(不超过十位):\n");
	scanf("%s", key);
	system("cls");
	printf("请再次输入您的密码,以确认无误。\n");
	scanf("%s", tmp);
	while (strcmp(tmp, key) != 0)
	{
		printf("抱歉!两次输入不一致,请检查后重新输入:\n");
		printf("请输入您的密码(不超过十位):\n");
		scanf("%s", key);
		system("cls");
		printf("请再次输入您的密码,以确认无误。\n");
		scanf("%s", tmp);
	}
	printf("创建成功!\n");
	printf("请牢记您的账号:%d\n", account);
	printf("密码:%s\n", key);
	Admi* p = (Admi*)malloc(sizeof(Admi));
	p->next = NULL;
	p->Id = account;
	strcpy(p->Key, key);
	if (tail)
	{
		tail->next = p;
		tail = p;
	}
	else
	{
		*head = p;
		tail = p;
	}
	return ;
}

void Login(Admi* head)
{
	int account;
	char key[KEY_LEN];
	int flag = 0;
	printf("请输入账号:\n");
	scanf("%d", &account);
	printf("请输入密码:\n");
	scanf("%s", key);
	while (head)
	{
		if (head->Id == account && strcmp(head->Key, key) == 0)
		{
			flag = 1;
			break;
		}
		head = head->next;
	}
	if (flag)
	{
		printf("登陆成功!\n");
		operation();
	}
	else
	{
		printf("登陆失败!\n");
		return;
	}
	//system("pause");
}


void to_copy()//复制
{
	char file_name[FILE_NAME_MAX_LEN];
	char copy_file_name[FILE_NAME_MAX_LEN];
	printf("请输入文件路径:\n");
	scanf("%s", file_name);

	printf("请问是否保存在当前路径下?\n");
	printf("是(1),否(0)\n");
	int select;
	scanf("%d", &select);
	if (select == 0)
	{
		printf("请输入新路径及名称:\n");
		scanf("%s", copy_file_name);
	}
	else
	{
		char end_name[10];
		cut_end_name(file_name, end_name);
		cut_name(file_name, copy_file_name);
		strcat(copy_file_name, "-副本");
		strcat(copy_file_name, end_name);
	}

	if (copy_file(file_name, copy_file_name) == 1)
		printf("复制完成!\n");
}


void to_delete()//删除
{
	char file_name[FILE_NAME_MAX_LEN];
	printf("请输入文件的完整路径:\n");
	scanf("%s", file_name);
	if (remove(file_name) == 0)printf("删除完成!\n");
	else printf("删除失败\n");

}


void to_cut()//剪切
{
	char file_name[FILE_NAME_MAX_LEN];
	char cut_file_name[FILE_NAME_MAX_LEN];
	printf("请输入文件的完整路径:\n");
	scanf("%s", file_name);
	printf("请输入文件剪切的目标路径:\n");
	scanf("%s", cut_file_name);

	if (copy_file(file_name, cut_file_name) == 1 && remove(file_name) == 0)
		printf("文件剪切成功!\n");

}

int copy_file(char* file_name, char* copy_file_name)//复制文件
{
	FILE* in_fp, * on_fp;
	in_fp = fopen(file_name, "rb");
	if (in_fp == NULL)
	{
		printf("文件读取失败!请检查是否写入的名称有误。\n");
		return -1;
	}
	on_fp = fopen(copy_file_name, "wb");
	if (on_fp == NULL)
	{
		printf("文件复制失败!请检查内存\n");
		return -1;
	}

	unsigned char ch;
	while (!feof(in_fp))
	{
		fread(&ch, sizeof(unsigned char), 1, in_fp);
		fwrite(&ch, sizeof(unsigned char), 1, on_fp);
	}

	fclose(in_fp);
	fclose(on_fp);
	return 1;
}

void to_Encrypted()//加密 
{
	char file_name[30], encry_file_name[30], temp_name[10] = "en_";

	printf("请输入需要加密的文件名:\n");
	scanf("%s", file_name);
	strcpy(encry_file_name, temp_name);
	strcat(encry_file_name, file_name);
	printf("是否使用默认命名:%s\n", encry_file_name);
	printf("是(1),否(0)\n");
	int select;
	scanf("%d", &select);
	if (select == 0)
	{
		printf("请输入加密后的文件名称:\n");
		scanf("%s", encry_file_name);
	}

	if (Encrypted(file_name, encry_file_name) == 1)
		printf("加密成功!\n");
	else
		printf("加密失败!\n");
}

void to_Unencrypted()//解密
{
	char file_name[30], unencry_file_name[30], temp_name[10] = "un_";
	char password[12];
	printf("请输入需要解密的文件名:\n");
	scanf("%s", file_name);

	printf("请输入密钥(不超过10个字符):\n");
	scanf("%10s", password);
	strcpy(unencry_file_name, temp_name);
	strcat(unencry_file_name, file_name);
	printf("是否使用默认命名:%s\n", unencry_file_name);
	printf("是(1),否(0)\n");
	int select;
	scanf("%d", &select);
	if (select == 0)
	{
		printf("请输入解密后的文件名称:\n");
		scanf("%s", unencry_file_name);
	}

	if (Unencrypted(file_name, unencry_file_name, password) == 1)
		printf("解密成功!\n");
	else
		printf("解密失败!\n");
}

void to_compress()//压缩
{
	int select;
	system("cls");
	while (1)
	{
		printf("************** 压缩页面 **************\n\n");
		printf("         1.压缩    2.压缩并加密\n\n");
		printf("         3.返回上一级\n");
		scanf("%d", &select);
		if (select == 1 || select == 2)break;
		if (select == 3)return;
		printf("输入有误,请选择正确的序号:\n");
		system("pause");
		system("cls");
	}
	system("cls");
	char file_name[FILE_NAME_MAX_LEN];
	char des_file_name[FILE_NAME_MAX_LEN];
	char com_file_name[FILE_NAME_MAX_LEN] = "co_";
	char encry_file_name[FILE_NAME_MAX_LEN] = "en_";
	printf("请输入要压缩的文件名:\n");
	scanf("%s", file_name);


	printf("文件是否使用默认命名?\n");
	printf("是(非零),否(零)\n");
	int t;
	scanf("%d", &t);
	if (t == 0)
	{
		printf("请输入文件名:\n");
		scanf("%s", des_file_name);
	}
	else
	{
		strcat(com_file_name, file_name);
		strcpy(des_file_name, com_file_name);
	}

	printf("正在压缩中。。。\n");
	clock_t start, end;
	start = clock();

	float rate;
	if (select == 2)//先压缩再加密
	{
		rate = compress(file_name, com_file_name);
		if (t == 0)//
		{
			Encrypted(com_file_name, des_file_name);
		}
		else//默认命名
		{
			strcat(encry_file_name, file_name);
			Encrypted(com_file_name, encry_file_name);
			strcpy(des_file_name, encry_file_name);
		}
		remove(com_file_name);//删除只压缩的文件
	}
	else//只有压缩
	{
		rate = compress(file_name, des_file_name);
	}

	end = clock();
	if (rate <= 0)return;//异常处理




	printf("压缩后文件名为:%s\n", des_file_name);
	rate *= 100;
	printf("压缩率为:%0.2f%%\n", rate);
	printf("压缩时间为:%0.2lfs\n", (double)(end - start) / CLK_TCK);// CLK_TCK=1000

}

void to_extract()//解压
{
	int select;
	system("cls");
	while (1)
	{
		printf("************** 解压页面 **************\n\n");
		printf("         1.解压    2.解密解压\n\n");
		printf("         3.返回上一级\n");
		scanf("%d", &select);
		if (select == 1 || select == 2)break;
		if (select == 3)return;
		printf("输入有误,请选择正确的序号:\n");
		system("pause");
		system("cls");
	}
	system("cls");
	char file_name[FILE_NAME_MAX_LEN];
	char ex_file_name[FILE_NAME_MAX_LEN] = "ex_";
	char unencry_file_name[FILE_NAME_MAX_LEN] = "un_";
	char password[KEY_LEN];
	printf("请输入要解压的文件名:\n");
	scanf("%s", file_name);

	if (select == 2)
	{
		printf("请输入密钥:\n");
		scanf("%10s", password);
		strcat(unencry_file_name, file_name);
		Unencrypted(file_name, unencry_file_name, password);
		strcpy(file_name, unencry_file_name);//
	}

	printf("文件是否使用默认命名?\n");
	printf("是(非零),否(零)\n");
	int t;
	scanf("%d", &t);
	if (t == 0)
	{
		printf("请输入文件名:\n");
		scanf("%s", ex_file_name);
	}
	else strcat(ex_file_name, file_name);

	printf("正在解压中。。。\n");
	clock_t start, end;
	start = clock();
	if (extract(file_name, ex_file_name) <= 0)return;//异常处理
	end = clock();

	if (select == 2)
	{
		remove(unencry_file_name);//删除
	}

	printf("解压后文件名为:%s\n", ex_file_name);
	printf("解压时间为:%0.2lfs\n", (double)(end - start) / CLK_TCK);// CLK_TCK=1000

}

//******************************    二级函数区  ******************************

void get_account(int* account)//自动生成账号
{
	*account = ++USER_CT;
}

void cut_name(const char* file_name, char* only_name)//剪切文件名称
{
	int len = strlen(file_name) - 1;
	while (file_name[len] != '.')
	{
		len--;
	}
	strncpy(only_name, file_name, len);
	only_name[len] = '\0';
}

void cut_end_name(const char* file_name, char* end_name)//剪切文件后缀
{
	int len = strlen(file_name) - 1;
	while (file_name[len] != '.')len--;
	strcpy(end_name, &file_name[len]);
}

int Encrypted(const char* file_name, const char* encry_file_name)//加密函数
{
	FILE* in_fp, * on_fp;
	in_fp = fopen(file_name, "rb");
	if (in_fp == NULL)
	{
		printf("文件读取失败!请检查是否写入的名称有误。\n");
		return -1;
	}
	on_fp = fopen(encry_file_name, "wb");
	if (on_fp == NULL)
	{
		printf("文件创建失败!请检查内存状况后重试。\n");
		return -1;
	}

	char password[KEY_LEN], tmp[KEY_LEN];
	printf("请输入密钥(不超过10个字符):\n");
	scanf("%10s", password);

	system("cls");
	printf("请再次输入密钥,以确认无误:\n");
	scanf("%10s", tmp);
	if (strcmp(password, tmp) != 0)
	{
		while (strcmp(password, tmp) != 0)
		{
			printf("两次输入不一致,请重新输入:\n");
			scanf("%10s", password);
			system("cls");
			printf("请再次输入密钥,以确认无误:\n");
			scanf("%10s", tmp);
		}
	}
	printf("密钥创建成功!\n");

	if (on_fp == NULL)
	{
		printf("文件创建失败!请检查内存。\n");
		return -1;
	}

	unsigned long part_ct = 0, file_len = 0;
	fseek(in_fp, 0, SEEK_END);
	file_len = ftell(in_fp);
	rewind(in_fp);//问题一

	if (file_len > PART_LEN)part_ct = PART_LEN;//最多加密长度PART_LEN
	else part_ct = file_len / 10 + 1;//防止为空,0

	unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * (part_ct + 1));//创建动态数组以储存原文本的part_ct 
	fread(data, sizeof(unsigned char), part_ct, in_fp);//读入part_ct部分的文件,此时文件指针part_ct处

	int password_len = strlen(password);
	for (int i = 0; i < part_ct / password_len + 1; i++)//进行循环异或操作
		for (int j = 0; j < password_len && (j + i * password_len) < part_ct; j++)
			data[j + i * password_len] ^= password[j];

	fwrite(data, sizeof(unsigned char), part_ct, on_fp);//将异或后的部分文件写入
	while (!feof(in_fp))
	{
		unsigned char ch;
		fread(&ch, sizeof(unsigned char), 1, in_fp);
		fwrite(&ch, sizeof(unsigned char), 1, on_fp);
	}
	free(data);//释放动态内存
	fclose(in_fp);
	fclose(on_fp);
	return 1;//成功
}

int Unencrypted(const char* file_name, const char* unencry_file_name, const char* password)//解密函数
{
	FILE* in_fp, * on_fp;
	in_fp = fopen(file_name, "rb");
	if (in_fp == NULL)
	{
		printf("文件读取失败!请检查是否写入的名称有误。\n");
		return -1;
	}
	on_fp = fopen(unencry_file_name, "wb");
	if (on_fp == NULL)
	{
		printf("文件创建失败!请检查内存。\n");
		return -1;
	}

	unsigned long part_ct = 0, file_len = 0;
	fseek(in_fp, 0, SEEK_END);
	file_len = ftell(in_fp);
	rewind(in_fp);//问题一

	if (file_len > PART_LEN)part_ct = PART_LEN;
	else part_ct = file_len / 10 + 1;//防止为空,0

	unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * (part_ct + 1));//创建动态数组以储存原文本的part_ct 
	fread(data, sizeof(unsigned char), part_ct, in_fp);//读入part_ct部分的文件,此时文件指针part_ct处

	int password_len = strlen(password);
	for (int i = 0; i < part_ct / password_len + 1; i++)//进行循环异或操作
		for (int j = 0; j < password_len && (j + i * password_len) < part_ct; j++)
			data[j + i * password_len] ^= password[j];

	fwrite(data, sizeof(unsigned char), part_ct, on_fp);//将异或后的部分文件写入
	while (!feof(in_fp))
	{
		unsigned char ch;
		fread(&ch, sizeof(unsigned char), 1, in_fp);
		fwrite(&ch, sizeof(unsigned char), 1, on_fp);
	}
	free(data);//释放动态内存
	fclose(in_fp);
	fclose(on_fp);
	return 1;//成功
}

void InitHafNode()
{
	for (int i = 0; i < 512; i++)
	{
		huf_tree[i].parent = -1;
		huf_tree[i].lch = -1;
		huf_tree[i].rch = -1;
		huf_tree[i].count = 0;
		huf_tree[i].bits[0] = 0;
	}
}

float compress(const char* filename, const char* outputfile)
{
	InitHafNode();
	char buf[512];
	unsigned char c;
	unsigned long flength;
	FILE* infp, * onfp;
	infp = fopen(filename, "rb");
	if (infp == NULL)
	{
		printf("打开文件失败:%s\n", filename);
		return 0;                             //如果打开失败,则输出错误信息
	}
	onfp = fopen(outputfile, "wb");                 //打开压缩后存储信息的文件
	if (onfp == NULL)
	{
		printf("打开文件失败:%s\n", outputfile);
		return 0;
	}
	flength = 0;
	while (!feof(infp))
	{
		fread(&c, 1, 1, infp);
		huf_tree[c].count++;                       //读文件,统计字符出现次数
		flength++;                               //记录文件的字符总数
	}
	flength--;
	huf_tree[c].count--;

	for (int i = 0; i < 512; i++)                    //HUFFMAN算法中初始节点的设置
	{
		if (huf_tree[i].count != 0)
			huf_tree[i].ch = (unsigned char)i;
		else
			huf_tree[i].ch = -1;
			
		huf_tree[i].parent = -1;
		huf_tree[i].lch = huf_tree[i].rch = -1;//
	}

	for (int i = 0; i < 256; i++)                    //将节点按出现次数排序,降序 
	{
		for (int j = i + 1; j < 256; j++)
		{
			if (huf_tree[i].count < huf_tree[j].count)
			{
				tmp = huf_tree[i];
				huf_tree[i] = huf_tree[j];
				huf_tree[j] = tmp;
			}
		}
	}

	int i;
	for (i = 0; i < 256; i++)                    //统计不同字符的数量
	{
		if (huf_tree[i].count == 0)
			break;
	}

	int n = i, j;
	int m = 2 * n - 1;
	long move, min;
	for (i = n; i < m; i++)//每次增加一个新节点,赋值给i,此时pt1用作中间量
	{
		min = 999999999;
		for (j = 0; j < i; j++)//找出当前最小
		{
			if (huf_tree[j].parent != -1) continue;
			if (min > huf_tree[j].count)
			{
				move = j;
				min = huf_tree[j].count;
			}
		}

		huf_tree[i].count = huf_tree[move].count;
		huf_tree[move].parent = i;
		huf_tree[i].lch = move;
		min = 999999999;
		for (j = 0; j < i; j++)//当前次小
		{
			if (huf_tree[j].parent != -1) continue;
			if (min > huf_tree[j].count)
			{
				move = j;
				min = huf_tree[j].count;
			}
		}
		huf_tree[i].count += huf_tree[move].count;
		huf_tree[i].rch = move;
		huf_tree[move].parent = i;
	}

	long f;
	for (i = 0; i < n; i++)                        //构造HUFFMAN树,设置字符的编码
	{
		f = i;
		huf_tree[i].bits[0] = 0;
		while (huf_tree[f].parent != -1)
		{
			j = f;
			f = huf_tree[f].parent;
			if (huf_tree[f].lch == j)
			{
				j = strlen(huf_tree[i].bits);
				memmove(huf_tree[i].bits + 1, huf_tree[i].bits, j + 1);//拷贝 
				huf_tree[i].bits[0] = '0';
			}
			else
			{
				j = strlen(huf_tree[i].bits);
				memmove(huf_tree[i].bits + 1, huf_tree[i].bits, j + 1);
				huf_tree[i].bits[0] = '1';
			}
		}
	}


	//下面的就是读原文件的每一个字符,按照设置好的编码替换文件中的字符
	fseek(infp, 0, SEEK_SET);                                                //将指针定在文件起始位置
	fseek(onfp, 8, SEEK_SET);                                //以8位二进制数为单位进行读取
	buf[0] = 0;
	f = 0;//字节个数 
	move = 8;//开始计数



	while (!feof(infp))
	{
		c = fgetc(infp);
		f++;
		for (i = 0; i < n; i++)
		{
			if (c == huf_tree[i].ch) break;
		}
		strcat(buf, huf_tree[i].bits);
		j = strlen(buf);
		c = 0;
		while (j >= 8)                                             //当剩余字符数量不小于8个时
		{
			for (i = 0; i < 8; i++)                               //按照八位二进制数转化成十进制ASCII码写入文件一次进行压缩
			{
				if (buf[i] == '1') c = (c << 1) | 1;
				else c = c << 1;
			}
			fwrite(&c, 1, 1, onfp);//
			move++;//
			strcpy(buf, buf + 8);
			j = strlen(buf);
		}

		if (f == flength)
			break;
	}


	if (j > 0)                                                      //当剩余字符数量少于8个时
	{
		strcat(buf, "00000000");
		for (i = 0; i < 8; i++)
		{
			if (buf[i] == '1') c = (c << 1) | 1;
			else c = c << 1;                                        //对不足的位数进行补零
		}
		fwrite(&c, 1, 1, onfp);
		move++;//
	}
	fseek(onfp, 0, SEEK_SET);                                        //将编码信息写入存储文件
	fwrite(&flength, 1, sizeof(flength), onfp);//文件长度 
	fwrite(&move, sizeof(long), 1, onfp);//
	fseek(onfp, move, SEEK_SET);//从文件开头偏移pt1
	fwrite(&n, sizeof(long), 1, onfp);//写入字符种类数
	for (i = 0; i < n; i++)
	{
		tmp = huf_tree[i];

		fwrite(&(huf_tree[i].ch), 1, 1, onfp);
		move++;//
		c = strlen(huf_tree[i].bits);
		fwrite(&c, 1, 1, onfp);
		move++;//
		j = strlen(huf_tree[i].bits);

		if (j % 8 != 0)                                             //当位数不满8时,对该数进行补零操作
		{
			for (f = j % 8; f < 8; f++)
				strcat(huf_tree[i].bits, "0");
		}

		while (huf_tree[i].bits[0] != 0)
		{
			c = 0;
			for (j = 0; j < 8; j++)
			{
				if (huf_tree[i].bits[j] == '1') c = (c << 1) | 1;
				else c = c << 1;
			}
			strcpy(huf_tree[i].bits, huf_tree[i].bits + 8);
			fwrite(&c, 1, 1, onfp);                                            //将所得的编码信息写入文件
			move++;// 
		}


	}

	fseek(onfp, 0, SEEK_END);
	int ct = ftell(onfp);

	fclose(infp);                                                             //关闭文件
	fclose(onfp);

	float rate = ct * 1.0 / flength;
	return rate;
}



//作用:解压缩文件,并将解压后的内容写入新文件
int extract(const char* filename, const char* outputfile)
{
	InitHafNode();                                                         //初始化

	char buf[255], bx[255];
	unsigned char uch;

	FILE* infp, * onfp;
	infp = fopen(filename, "rb");                                              //打开文件
	if (infp == NULL)
	{
		printf("文件读取失败!请检查文件名后重试。\n");
		return 0;     //若打开失败,则输出错误信息
	}

	onfp = fopen(outputfile, "wb");                                            //打开文件
	if (onfp == NULL)
	{
		printf("文件创建失败!请检查内存后重试。\n");
		return 0;
	}

	long flength, move, char_kinds;                                                        //01读取原来文本信息
	fread(&flength, sizeof(long), 1, infp);                                    //读取原文件长
	fread(&move, sizeof(long), 1, infp);                                          //读取pt1偏移量
	fseek(infp, move, SEEK_SET);                                                  //从文件开头偏移pt1
	fread(&char_kinds, sizeof(long), 1, infp);                                          //读取字符种类数


	for (int i = 0, m, j, len; i < char_kinds; i++)                                         //02读取压缩文件内容并转换成二进制码哈夫曼编码
	{
		fread(&huf_tree[i].ch, 1, 1, infp);//读取字符
		fread(&uch, 1, 1, infp);//读取编码长度
		len = (long)uch;
		huf_tree[i].count = len;
		huf_tree[i].bits[0] = 0;

		if (len % 8 > 0) m = len / 8 + 1;//上取整,补够整8位
		else m = len / 8;//

		for (j = 0; j < m; j++)
		{
			fread(&uch, 1, 1, infp);
			move = uch;
			_itoa(move, buf, 2);//按二进制转换,开头的0被忽略,要补齐
			move = strlen(buf);
			for (int t = 8; t > move; t--)
			{
				strcat(huf_tree[i].bits, "0");                                  //位数不足,执行前补零操作
			}
			strcat(huf_tree[i].bits, buf);
		}
		huf_tree[i].bits[len] = 0;//编码终止
	}


	for (int i = 0; i < char_kinds; i++)                               //从小到大排序
	{
		for (int j = i + 1; j < char_kinds; j++)
		{
			if (strlen(huf_tree[i].bits) > strlen(huf_tree[j].bits))
			{
				tmp = huf_tree[i];
				huf_tree[i] = huf_tree[j];
				huf_tree[j] = tmp;
			}
		}
	}


	int p = strlen(huf_tree[char_kinds - 1].bits);        //最大编码长度
	fseek(infp, 8, SEEK_SET);                   //从开头偏移8
	int ct = 0;
	bx[0] = 0;

	int i;
	while (1)
	{
		while (strlen(bx) < (unsigned int)p)
		{
			fread(&uch, 1, 1, infp);
			move = uch;
			_itoa(move, buf, 2);
			move = strlen(buf);
			for (int t = 8; t > move; t--)
			{
				strcat(bx, "0");
			}
			strcat(bx, buf);
		}
		for (i = 0; i < char_kinds; i++)
		{
			if (memcmp(huf_tree[i].bits, bx, huf_tree[i].count) == 0) break;
		}
		strcpy(bx, bx + huf_tree[i].count);
		uch = huf_tree[i].ch;
		fwrite(&uch, 1, 1, onfp);
		ct++;

		if (ct == flength) break;//读取完毕,feof会多读取,有误差
	}


	fclose(infp);
	fclose(onfp);
	return 1;
}

void operation()//供login()调用
{
	system("cls");
	int select;
	while (1)
	{
		menu2();
		scanf("%d", &select);
		switch (select)
		{
		case 1:to_compress(); break;//先压缩后加密,节省时间
		case 2:to_extract(); break;//若加密了请先输入,密钥
		case 3:to_Encrypted(); break;//加密
		case 4:to_Unencrypted(); break;//解密
		case 5:to_delete(); break;//删除
		case 6:to_copy(); break;//复制
		case 7:to_cut(); break;//剪切
		case 8:return;
		default:printf("请输入对应的数字\n");
		}
		system("pause");
		system("cls");
	}
}

void saveAd(Admi* head)//退出程序保存信息
{
	FILE* fp;
	fp = fopen("账号密码.txt", "w");
	if (fp == NULL)
	{
		printf("账号信息保存失败!\n");
		return;
	}
	fprintf(fp, "%d\n", USER_CT);
	while (head)
	{
		fprintf(fp, "%d %s\n", head->Id, head->Key);
		head = head->next;
	}
	fclose(fp);
	system("pause"); 
}

Admi* getAd()//读取账号信息
{
	FILE* fp;
	fp = fopen("账号密码.txt", "a+");
	if (fp == NULL)
	{
		printf("账号信息读取失败!\n");
		exit(1);
		return NULL;
	}
	Admi* tmp, * head = NULL;

	if (fscanf(fp, "%d\n", &(USER_CT)) == EOF)//
	{
		USER_CT = 1000;
		fclose(fp);
		return NULL;
	}

	while (!feof(fp))
	{
		tmp = (Admi*)malloc(sizeof(Admi));
		tmp->next = NULL;
		fscanf(fp, "%d %s\n", &(tmp->Id), tmp->Key);
		if (head == NULL)
		{
			head = tmp;
			tail = tmp;
		}
		else
		{
			tail->next = tmp;
			tail = tmp;
		}

	}
	fclose(fp);
	return head;

}

//---------------------------主函数-------------------------------------

int main(int argc, char* argv[])
{
	system("mode con cols=60 lines=30");
	system("color 0B");//背景与字体颜色
	GetCurrentDirectory(110, file_path);
	strcat(file_path, "\\");//得到当前文件路径
	int select = 0;
	Admi* head = NULL;
	head = getAd();//读取账号信息
	while (1)
	{
		menu1();
		scanf("%d", &select);
		switch (select)
		{
		case 1:CreateAd(&head); break;
		case 2:Login(head); break;
		case 3:saveAd(head); exit(0); break;
		default:printf("请输入对应的数字\n");
		}
		system("pause");
		system("cls");
	}
	return 0;
}

你可能感兴趣的:(c语言,开发语言,c++)