文件打包解包

基于文件IO的文件打包和解包

通过命令行传参的方式,获取文件的路径和基本信息

遍历目录的结构

void findfile(char *Path);

int main(int argc, char **argv)
{
	struct _stat buf;
	int result;

	char Path[256] = { 0 };

	//cout << "文件名:" << endl;
	for (size_t i = 1; i < argc; i++)
	{
		cout << i << ":" << argv[i] << endl;
		result = _stat(argv[i], &buf);
		if (_S_IFDIR & buf.st_mode) {
			printf("folder\n");
			//strcpy(Path, argv[i]);
			sprintf(Path, "%s\\*", argv[i]);
			//cout << Path << endl;
			findfile(Path);
		}
		else if (_S_IFREG & buf.st_mode) {
			printf("file\n");
		}
	}

	while (1);
	return 0;
}

void findfile(char *Path) {
	_finddata_t fileDir;
	intptr_t HANDLE;

	HANDLE = _findfirst(Path, &fileDir);
	if (HANDLE == -1)
		printf("No file is found\n");
	else {
		printf("file list:\n");
		do {
			//判断是否有子目录  
			if (fileDir.attrib & _A_SUBDIR){
				//判断是否为"."当前目录,".."上一层目录
				if ((strcmp(fileDir.name, ".") != 0) && (strcmp(fileDir.name, "..") != 0))
				{
					char newPath[256] = { 0 };
					memcpy(newPath, Path, (strlen(Path)-1));
					sprintf(newPath, "%s\%s\\*", newPath, fileDir.name);
					findfile(newPath);
				}
			}
			else{
				cout <<"\t" << fileDir.name << endl;
			}
		} while (_findnext(HANDLE, &fileDir) == 0);
	}

}

文件打包

通过命令行的参数获取到了要打包文件的个数和要打包文件的路径名,

新建一个打包文件,将四字节的文件个数先写入到打包文件中,方便解包的时候获取,

并按文件个数循环获取文件的大小和文件的路径名,并保存在文件信息结构体数组中,将这个文件信息结构体数组也写入到新建的打包文件中,方便解包时获取,

按文件个数和文件路径名循环读取文件的内容并追加到新建打包文件的末尾。

  1. 文件信息结构体(包含文件的大小和文件的路径名)

    //文件信息结构体
    struct DaBao{
    	int filesize;
    	char filename[256];
    };
    
  2. 获取文件的大小

    //获取文件大小
    int GetFileSzie(char *filename) {
    	//打开文件
    	FILE* fp = fopen(filename, "r");
    	if (NULL == fp) return -1;            //打开失败
    
    	//设置文件指针到文件末尾
    	fseek(fp, 0, SEEK_END);
    
    	//获取文件内容指针到文件头的 大小
    	int size = ftell(fp);
    
    	//设置文件指针到文件头 还原
    	fseek(fp, 0, SEEK_SET);
    
    	//关闭文件
    	fclose(fp);
    
    	//返回文件大小
    	return size;
    }
    
  3. 保存文件信息(文件大小、文件路径名)到文件信息结构体中

    //文件信息保存   --获取文件名和文件大小
    void SaveFileInfo(struct DaBao *fileinfo, int num, char **argv) {
    	for (size_t i = 0; i < num; i++) {
    		//文件名
    		strcpy(fileinfo[i].filename, argv[i + 1]);
    		//文件大小
    		fileinfo[i].filesize = GetFileSzie(argv[i + 1]);
    
    		//日志
    		cout << i+1 << ":文件名:" << fileinfo[i].filename << " 文件大小:" << fileinfo[i].filesize << endl;
    	}
    }
    
  4. 把文件内容追加到新建文件的末尾

    //把文件内容写进去
    void fWrite(struct DaBao *fileinfo, FILE *fp, int num) {
    	FILE *fpSrc;
    	char buf[1024];
    	int n = 0;
    	cout << num << endl;
    	for (size_t i = 0; i < num; i++) {
    		//打开文件
    		fpSrc = fopen(fileinfo[i].filename, "rb");
    		if (fpSrc != NULL) {
    			cout << fileinfo[i].filename << "文件打开成功" << endl;
    		}
    
    		//读取文件内容
    		while (1) {
    			memset(buf, 0x00, sizeof(buf));
    			n = fread(buf, 1, sizeof(buf), fpSrc);  //读内容
    			cout << n << endl;
    			if (n > 0) {
    				fwrite(buf, 1, n, fp);    //写内容
    			}
    			else {
    				cout << fileinfo[i].filename << "文件写入成功" << endl;
    				break;
    			}
    		}
    
    		//关闭文件
    		fclose(fpSrc);
    	}
    }
    
  5. 主函数流程

    int main(int argc, char **argv)
    {
    	//要打包的文件个数
    	int num = argc - 1;
    
    	//文件信息数组
    	struct DaBao *fileinfo = (struct DaBao*)malloc(num * sizeof(struct DaBao));
    
    	//文件信息保存   --获取文件名和文件大小
    	SaveFileInfo(fileinfo, num, argv);
    
    	//创建打包后的文件
    	FILE *fp = fopen("dabao.sixsizsiz", "wb");
    	if (fp != NULL) {
    		cout << "打包文件创建成功" << endl;
    	}
    
    	//把文件个数写进去
    	fwrite(&num, 1, 4, fp);
    
    	//把文件信息写进去
    	fwrite(fileinfo, num * sizeof(struct DaBao), 1, fp);
    	cout << "准备已就绪" << endl;
    
    	//把文件内容写进去
    	fWrite(fileinfo, fp, num);
    	cout << "文件已打包完成" << endl;
    
    	//关闭文件
    	fclose(fp);
    
    	while (1);
    	return 0;
    }
    

文件解包

  1. 打开文件
  2. 读取包装文件内的文件个数
  3. 按文件个数循环读取文件的信息(文件大小和文件路径名)保存在文件信息结构体数组中
  4. 按文件个数和文件信息结构体循环创建新的文件并读取文件内容写入到解包文件中。
#include <iostream>

using namespace std;

//文件信息结构体
struct JieBao {
	int filesize;
	char filename[256];
};

//创建并写入解包问文件
void fWite(FILE *fp, struct JieBao *fileinfo, int num);

int main(int argc, char **argv)
{
	//打开文件
	FILE *fp = fopen(argv[1], "rb");
	if (fp != NULL) {
		cout << "包装文件打开成功" << endl;
	}

	//读取包装文件内的文件个数
	int num;
	fread(&num, 1, 4, fp);
	cout << "包装文件个数:" << num << endl;

	//读取每个文件的信息
	struct JieBao *fileinfo = (struct JieBao *)malloc(num * sizeof(struct JieBao));
	fread(fileinfo, 1, num * sizeof(struct JieBao), fp);

	//创建并写入解包问文件
	fWite(fp, fileinfo, num);

	//日志
	cout << "解压成功:" << endl;
	for (size_t k = 0; k < num; k++){
		cout << k+1 << ":文件名:" << fileinfo[k].filename << " 文件大小:" << fileinfo[k].filesize << endl;
	}

	//关闭文件
	fclose(fp);

	while (1);
	return 0;
}

//创建并写入解包问文件
void fWite(FILE *fp, struct JieBao *fileinfo, int num) {
	FILE *fpDst;
	char c;
	int n;
	for (size_t i = 0; i < num; i++) {
		//创建解包文件
		fpDst = fopen(fileinfo[i].filename, "wb");
		if (fpDst != NULL) {
			cout << "解包文件" << fileinfo[i].filename << "创建成功" << endl;
		}

		//读取内容并写入到解包文件
		for (size_t j = 0; j < fileinfo[i].filesize; j++) {
			fread(&c, 1, 1, fp);      //读取
			fwrite(&c, 1, 1, fpDst);  //写入
		}

		//关闭文件
		fclose(fpDst);
	}
}
void CPackDlg::OnBtnPack() { // TODO: Add your control notification handler code here CFileDialog savedlg(FALSE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"(类型:*.free)|*.free||"); if (IDOK != savedlg.DoModal()) return; int nTimeBegin = time(NULL); int nMiliTimeBegin = timeGetTime(); CString strPathName = savedlg.GetPathName(); CString strExt = savedlg.GetFileExt(); if (strExt!="free") strPathName+=".free"; int nFileNum = m_listFile.GetCount(); m_progress.SetRange(0,nFileNum); FILE* pFilePack = fopen(strPathName.GetBuffer(0),"wb"); if(!pFilePack) return; int nNumWrite = fwrite(&nFileNum;,sizeof(int),1,pFilePack); for (int i=0;i<nFileNum;i++) { CString str; m_listFile.GetText(i,str); int nFileNameLen = str.GetLength(); fwrite(&nFileNameLen;,sizeof(int),1,pFilePack); fwrite(str.GetBuffer(0),1,nFileNameLen,pFilePack); FILE* pFileOri = fopen(str.GetBuffer(0),"rb"); if (!pFileOri) { char buf[256]; sprintf(buf,"文件:\"%s\"不存在,打包失败!",str.GetBuffer(0)); fclose(pFilePack); MessageBox(buf); return; } fseek(pFileOri,0,SEEK_END); int nFileSize = ftell(pFileOri); fwrite(&nFileSize;,1,sizeof(int),pFilePack); fseek(pFileOri,0,SEEK_SET); // //方法一:这种方法效率比较低 // while(nFileSize-->0) // { // char c; // fread(&c,1,1,pFileOri); // fwrite(&c,1,1,pFilePack); // } //方法二:这种方法效率比较高 char *pBuf = new char[nFileSize]; fread(pBuf,1,nFileSize,pFileOri); fwrite(pBuf,1,nFileSize,pFilePack); delete []pBuf; m_progress.SetPos(i+1); fclose(pFileOri); } fclose(pFilePack); int nTimeEnd = time(NULL); int nMiliTimeEnd = timeGetTime(); char bufTime[128] = ""; char bufMiliTime[128] = ""; sprintf(bufTime,"打包用时:%d秒",nTimeEnd-nTimeBegin); sprintf(bufMiliTime,"打包用时:%d毫秒",nMiliTimeEnd-nMiliTimeBegin); if (nTimeEnd-nTimeBegin==0) MessageBox(bufMiliTime); else MessageBox(bufTime); } void CPackDlg::OnBtnUnpack() { // TODO: Add your control notification handler code here CStrin
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值