/* 要求能够将多个文件合并为一个文件,并且能够将被打包文件再次释放。 */ #include <iostream> #include <stdio.h> #include <stdlib.h> #include <memory.h> #include <string.h> #include <errno.h> using namespace std; //最多打包文件个数 #define MAX_FILE_COUNT 1024 //最大路径字符长度 #define MAX_PATH 260 //文件头 struct FileHead { unsigned int FileCount;//文件个数 unsigned int FileLen[MAX_FILE_COUNT];//文件大小 char FileName[MAX_FILE_COUNT][MAX_PATH];//文件名 }; //制作CAB文件的类对象 class MyCab { private: FileHead fh;//文件头 char ObjectFilePathName[MAX_PATH];//生成打包文件位置及名称 public: //无参数构造 MyCab() { memset(&fh,0x0,sizeof(fh)); memset(ObjectFilePathName,0x0,sizeof(ObjectFilePathName)); } public: //添加文件到包内 void AddFile(char * FilePathName) { if ( fh.FileCount >= MAX_FILE_COUNT - 1 ) { cout<<"最多支持"<<MAX_FILE_COUNT<<"个文件"<<endl; return; } strcpy(fh.FileName[fh.FileCount],FilePathName); fh.FileCount++; } //设置打包输出文件 void SetOutPutFile(char * OutFile) { memset(ObjectFilePathName,0x0,sizeof(ObjectFilePathName)); strcpy(ObjectFilePathName,OutFile); } //获取文件大小(传入以二进制方式打开的文件指针) long GetFileSize(FILE *pf) { //指针移到文件尾 fseek(pf,0,/*SEEK_END*/ 2); return ftell(pf);//fseek()不像lseek()会返回读写位置,因此必须使用ftell()来取得目前读写的位置。 } //制作打包文件 void DoMakeCAB() { if ( fh.FileCount < 1 ) { cout<<"没有文件添加到打包"<<endl; return; } if ( strlen(ObjectFilePathName) < 1 )//计算字符串s的(unsigned int型)长度,不包括'\0'在内 { cout<<"没有指定打包文件输出位置"<<endl; return; } FILE *pOutFile = NULL; FILE *pWorkFile = NULL; //获取所有文件大小 for ( int i = 0 ; i < fh.FileCount ; i++ )//i为文件的个数 { pWorkFile = fopen(fh.FileName[i],"rb"); if ( NULL == pWorkFile ) { cout<<"文件:"<<fh.FileName[i]<<"无法读取["<<strerror(errno)<<"]"<<endl; return; } fh.FileLen[i] = GetFileSize(pWorkFile); fclose(pWorkFile); } //开始合并写文件 pOutFile = fopen(ObjectFilePathName,"wb"); if ( NULL == pOutFile ) { cout<<"输出文件创建失败["<<strerror(errno)<<"]"<<endl; return; } //写入文件头 fwrite(&fh,sizeof(fh),1,pOutFile); //写入各文件 for ( int i = 0 ; i < fh.FileCount ; i++ ) { unsigned char *pTmpData = NULL; pWorkFile = fopen(fh.FileName[i],"rb"); if ( NULL == pWorkFile ) { cout<<"文件:"<<fh.FileName[i]<<"无法读取["<<strerror(errno)<<"]"<<endl; fclose(pWorkFile); fclose(pOutFile); return; } pTmpData = new unsigned char[fh.FileLen[i]]; fread(pTmpData,fh.FileLen[i],1,pWorkFile); if ( ferror(pWorkFile) ) { cout<<"文件:"<<fh.FileName[i]<<"无法读取["<<strerror(errno)<<"]"<<endl; fclose(pWorkFile); fclose(pOutFile); return; } fwrite(pTmpData,fh.FileLen[i],1,pOutFile); if ( ferror(pOutFile) ) { cout<<"文件:"<<ObjectFilePathName<<"无法写入["<<strerror(errno)<<"]"<<endl; fclose(pWorkFile); fclose(pOutFile); return; } delete [] pTmpData; fclose(pWorkFile); } fclose(pOutFile); cout<<"打包完成"<<endl; } //解包(为了节省时间不写错误处理了,可以根据上面自己添加) void DoUnCAB(char *CabFilePathName) { FILE *pCAB = NULL; FILE *pWork = NULL; pCAB = fopen(CabFilePathName,"rb"); //读文件头 memset(&fh,0x0,sizeof(fh)); fread(&fh,sizeof(fh),1,pCAB); printCAB(); //解包的所有文件放到当前目录下 for ( int i = 0 ; i < fh.FileCount ; i++ ) { unsigned char *pTmpData = NULL; pTmpData = new unsigned char[fh.FileLen[i]]; fread(pTmpData,fh.FileLen[i],1,pCAB); //只取文件名,不要生成文件的路径名 char tmpFileName[MAX_PATH]; char *ptmpC = fh.FileName[i] + strlen(fh.FileName[i]); while( '\\' != *ptmpC) { ptmpC--; } memset(tmpFileName,0x0,sizeof(tmpFileName)); strcpy(tmpFileName,ptmpC+1); //取CAB文件路径 char tmpPathName[MAX_PATH]; memset(tmpPathName,0x0,sizeof(tmpPathName)); strcpy(tmpPathName,CabFilePathName); ptmpC = tmpPathName + strlen(tmpPathName); while('\\' != *ptmpC) { ptmpC--; } ptmpC++; *ptmpC = '\0'; strcat(tmpPathName,tmpFileName); pWork = fopen(tmpPathName,"wb"); fwrite(pTmpData,fh.FileLen[i],1,pWork); fclose(pWork); delete [] pTmpData; } fclose(pCAB); } private: //显示打包内文件信息 void printCAB() { cout<<"文件内信息如下:"<<endl; cout<<"文件总数:"<<fh.FileCount<<endl; for ( int i = 0 ; i < fh.FileCount ; i++ ) { cout<<fh.FileName[i]<<"\t\t\t\t"<<fh.FileLen[i]<<"字节"<<endl; } } }; //使用方法: int main(void) { //--------------------打包过程-------------------- //声明对象 MyCab mc; //设置输出文件 mc.SetOutPutFile("d:\\mycabs\\my.cab"); //添加要打包的文件 mc.AddFile("c:\\aa.jpg"); mc.AddFile("c:\\aa.xls"); //执行打包 mc.DoMakeCAB(); //--------------------解过程-------------------- //声明对象 MyCab umc; //执行解包 umc.DoUnCAB("d:\\mycabs\\my.cab"); cin.clear(); cin.get(); }
要求能够将多个文件合并为一个文件,并且能够将被打包文件再次释放
最新推荐文章于 2022-04-24 11:00:05 发布