C++IO流 day9(拓展:文件加密与打包)

文件加密

#include <iostream>
#include <fstream>
int main(int argc,char* argv[])
{
	std::fstream SourceFile; 
	SourceFile.open(argv[1], std::ios::in | std::ios::binary);//源文件
	std::fstream DistFile; 
	DistFile.open("xiaogua.png", std::ios::out | std::ios::binary);//目标加密文件
	char temp;//定义一个临时的字符变量
	SourceFile.seekg(0, std::ios::end);//设置文件内容指针到文件末尾
	std::streamoff fileSize = SourceFile.tellg();//获取文件内容指针到文件头的字节数
	SourceFile.seekg(0, std::ios::beg);//设置文件内容指针返回到文件头
	for (std::streamoff i = 0; i < fileSize; i++)
	{
		temp = SourceFile.get();
		temp = (temp + 10) ^ 20;//二次加密
		DistFile.put(temp);//写入到目标文件
	}
	SourceFile.close();
	DistFile.close();
	return 0;
}
  • 操作演示:
    • 我们此时运行程序是会报错的,因为采用的命令行的方式提取文件,运行是没有文件的一定会报错,我们需要将图片拖入生成加密的exe程序中
      在这里插入图片描述

    • 然后会生成一个xiaogua.png加密的格式文件
      在这里插入图片描述

    • 此时这个文件就加密了,我们可以用winhex看看文件是否被加密
      在这里插入图片描述

    • 此时就可以看出这个png被二次运算了,程序里面是先加10后异或20,那么我们需要解密就是先异或20后减10,注意20在winhex里面是采用16进制,也就是在winhex里面要异或14
      请添加图片描述

    • 此时xiaogua.png文件就解密成功了
      在这里插入图片描述

拓展文件加密器功能

  • 我们可以使用Windows的库来将生成的文件删除,然后只剩下加密的源文件,这次采用一次异或加密,就可以做到加密解密同一个程序完成,至于为什么参考异或运算的法则,使用windows库时记得把项目属性改成多字节字符集
    在这里插入图片描述
  • 代码如下:
#include <iostream>
#include <fstream>
#include <windows.h>
int main(int argc,char* argv[])
{
	std::fstream SourceFile; 
	SourceFile.open(argv[1], std::ios::in | std::ios::binary);//源文件
	std::fstream DistFile; 
	DistFile.open("xiaogua.png", std::ios::out | std::ios::binary);//目标加密文件
	if (!SourceFile || !DistFile)
	{
		std::cout << "打开文件失败" << std::endl;
	}
	char temp;//定义一个临时的字符变量
	SourceFile.seekg(0, std::ios::end);//设置文件内容指针到文件末尾
	std::streamoff fileSize = SourceFile.tellg();//获取文件内容指针到文件头的字节数
	SourceFile.seekg(0, std::ios::beg);//设置文件内容指针返回到文件头
	for (std::streamoff i = 0; i < fileSize; i++)
	{
		temp = SourceFile.get();
		temp ^= 20;//加密
		DistFile.put(temp);//写入到目标文件
	}
	SourceFile.close();
	DistFile.close();
	DeleteFile(argv[1]);//删除还没有加密的原文件
	MoveFile("xiaogua.png", argv[1]);//将原名改为加密后的文件名
	return 0;
}
  • 结果
    请添加图片描述

文件打包与解包

  • 首先把项目属性改成多字节字符集
  • 打包思路:简单模拟一下文件打包,文件打包存放信息,有文件信息与文件内容,所以我们可以建立一个结构体用来存储文件的大小和文件名,然后获取到文件数量后分配一段文件多少的内存,将每个文件名存入到结构体中,然后将每个文件的大小存入结构体中,最后将每个文件大小个数和内容信息写入目标打包文件中
#include <iostream>
#include <fstream>
#include <windows.h>
struct fileInfo
{
	//建议字符串内存给大点
	char fileName[1024];//文件名
	std::streamoff fileSize;//文件大小
};
int main(int argc, char* argv[])
{
	//获取文件数量
	int numFile = argc - 1;
	//动态内存分配一段文件大小
	fileInfo* FileArr = new fileInfo[numFile];
	memset(FileArr, 0, numFile * sizeof(fileInfo));
	//保存每个文件名
	for (int i = 0; i < numFile; i++)
	{
		strcpy(FileArr[i].fileName, argv[i + 1]);//保存文件名
	}
	std::fstream SourceFile;
	std::fstream distFile;
	distFile.open("xiaogua.xiaogua", std::ios::out | std::ios::binary);
	//保存每个文件大小
	for (int i = 0; i < numFile; i++)
	{
		SourceFile.open(FileArr[i].fileName, std::ios::in | std::ios::binary);
		SourceFile.seekg(0, std::ios::end);
		FileArr[i].fileSize = SourceFile.tellg();
		SourceFile.seekg(0, std::ios::beg);
		SourceFile.close();
	}
	//文件个数信息写入打包文件中
	distFile.write((char*)&numFile, sizeof(int));
	//文件大小信息写入打包文件中
	distFile.write((char*)FileArr, numFile * sizeof(fileInfo));
	//循环写入打包文件
	for (int i = 0; i < numFile; i++)
	{
		SourceFile.open(FileArr[i].fileName, std::ios::in | std::ios::binary);
		for (std::streamoff j = 0; j < FileArr[i].fileSize; j++)
		{
			distFile.put(SourceFile.get());
		}
		SourceFile.close();
	}
	distFile.close();
	return 0;
}
  • 解包思路:首先得获取文件的数量,从命令行中获取到文件,读出文件数量,然后分配这个数量的内存,直接一次性读出文件信息,循环创建写入文件即可
#include <iostream>
#include <fstream>
#include <windows.h>
struct fileInfo
{
	//建议字符串内存给大点
	char fileName[1024];//文件名
	std::streamoff fileSize;//文件大小
};
int main(int argc, char* argv[])
{

	int numFile;//文件数量
	std::fstream SourceFile, distFile;
	//读取文件大小
	SourceFile.open(argv[1], std::ios::in | std::ios::binary);
	SourceFile.read((char*)&numFile, sizeof(int));
	//申请一段文件内存
	fileInfo* fileArr = new fileInfo[numFile];
	memset(fileArr, 0, numFile * sizeof(fileInfo));

	//从文件中读出要解包的文件信息
	/*for (int i = 0; i < numFile; i++)//等同下面一句,因为是数组可以一次性读出
	{
		SourceFile.read((char*)&fileArr[i], sizeof(fileInfo));
	}*/
	SourceFile.read((char*)fileArr, numFile * sizeof(fileInfo));//一次性读出

	//循环创建写入文件
	for (int i = 0; i < numFile; i++)
	{
		distFile.open(fileArr[i].fileName, std::ios::out | std::ios::binary);
		for (std::streamoff j = 0; j < fileArr[i].fileSize; j++)
		{
			distFile.put(SourceFile.get());
		}
		distFile.close();
	}
	SourceFile.close();
	return 0;
}
  • 运行结果
    请添加图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值