继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

文件(含多级子目录)的打包和解包 C++代码实现(中)

芜湖不芜
关注TA
已关注
手记 327
粉丝 75
获赞 334

上次博文说到了文件的打包,这次咱们来说一说文件夹的打包。

  要打包的文件夹可能有很多,单个文件夹的子目录也未知,所以需要逐一遍历文件夹的所有子目录!这个接口大家应该已经知道了(还不知道的,快去pick我的上篇博文O(∩_∩)O~) 程序员必备:思路清晰,那我就假装是一名合格的程序媛,故千辛万苦画了一张图,更直接明了地表达下我的观点和做法:

  https://img2.mukewang.com/5b778b670001390910450490.jpg

 

 

 

 

 

 

 

 

 

 

 

  要打包的文件夹:Folder1、Folder2、Folder3,其 绝对 路径分别为:C:/Users/Folder1、D:tmp/Folder2、D:Folder3; 要求:打包在E:/Test/Pack下

  采用什么样的打包方式才会保留不同文件夹、单个文件夹下不同子文件的分层对应关系呢?毕竟还得实现解包,总要实现解包在哪一具体路径下吧!!! 深思良久之后,终于天道酬勤,让我想到了解决方案,上篇博文也有提到,但还是想好好解(得)释(瑟)下:对于打包来说,要打包的全路径是放在参数vector 中的,即:已知的。那这种全路径信息要不要保存在最终打包的.dat中呢?其实是没必要的,因为我们要它的全路径没用。举栗:Folder1文件夹,它的路径C:/Users/Folder1 ,打包在E:/Test/Pack下,如果保留其真正所在的全路径,作为文件必备信息放在.dat中,那解包的时候它的路径就会是:E:/Test/Pack/C:/Users/Folder1,这种路径怎么会创建新的文件夹呢。又有小伙伴可能会提问,不保留路径信息不就ok了吗,那我试问,解包的时候又如何知道一层一层的对应关系呢。

  (重点)若是要打包的文件夹,如:Folder1、Folder2、Folder3,就把其路径=其文件夹名;若是subFolder1、subFolder2、subFolder3....这种子目录,亦或是1.txt、2.avi、3.dll...这种子子目录,我们就设置其路径为针对其打包级别的父目录:即:第一层保存路径为:Folder1、Folder2、Folder3;第二层保存路径为:Folder1/subFolder1、Folder1/subFolder2;第三层为:Folder1/subFolder1/1.txt、Folder1/subFolder2/foler1;第四层为:Folder1/subFolder2/foler1/2.avi;Folder1/subFolder2/foler1/3.dll

来,让我们撸代码:文件夹部分倾情奉献~

复制代码

 1     int folderCount = directories.size(); //vector一共保存了多少个文件夹 2     int sum = 0, subNum = 0; 3     for (size_t i = 0; i < folderCount; i++) 4     { 5         vector<string>AllSubFiles; 6         GetAllSubFiles(directories[i], AllSubFiles); 7         subNum = AllSubFiles.size(); 8         sum += subNum; 9     }10     sum += folderCount;11     fwrite(&sum, sizeof(sum), 1, wfp); //用路径法解决:不同层别关系的解包,即:记录文件夹+其子目录的所有个数,写入打包文件12 13     int j = 0;14     for (int i = 0; i < folderCount; i++)15     {16         struct FolderInfo folder;17 18         string DirName = getFileNameFromPath(directories[i]);19         strcpy(folder.Filepath, DirName.c_str()); //路径20         strcpy(folder.FolderName, DirName.c_str()); //名字21         folder.FolderNameLen = strlen(DirName.c_str()); //名字长度22         folder.FileSize = 0; //文件夹大小23         folder.type = 1;24 25         fwrite(&folder, sizeof(folder), 1, wfp); 文件夹信息写入打包文件26         cout << "folderName:" << folder.FolderName << "; nameLength:" << folder.FolderNameLen << "; path:" << folder.Filepath << ", fileSize:" << folder.FileSize << "; type:" << folder.type << endl;27 28         vector<string>AllSubFile;29         vector<string>::iterator newIt;30         GetAllSubFiles(directories[i], AllSubFile); //遍历子文件目录31         int count = AllSubFile.size();32         33         for (newIt = AllSubFile.begin(); newIt != AllSubFile.end(); newIt++)34         {35             struct FolderInfo fileInDir;36 37             //自定义相对路径函数:38             string FolderPath = directories[i]; //文件夹路径39             string SubPath = *newIt;//子目录路径40 41             int n1 = strlen(FolderPath.c_str());42             int n2 = strlen((*newIt).c_str());43 44             string _str;45             for (size_t i = n1 + 1; i < n2; i++)46             {47                 _str += SubPath[i];48             }49             string str = DirName + '\\' + _str;50 51             strcpy(fileInDir.Filepath, str.c_str()); //相对路径52             string subFileName = getFileNameFromPath(*newIt);53             strcpy(fileInDir.FolderName, subFileName.c_str());//名字54             fileInDir.FolderNameLen = strlen(subFileName.c_str());//名字长度55 56             ifstream DirFile;57             DirFile.open(SubPath, ios::binary);58 59             DirFile.seekg(0, ios::end);60             streampos Fsize = DirFile.tellg();61             fileInDir.FileSize = Fsize;62 63             WIN32_FIND_DATAA FindFileData;64             FindFirstFileA((*newIt).c_str(), &FindFileData);65             if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)66             {67 68                 fileInDir.type = 1;//文件夹类型69             }70             else71             {72                 fileInDir.type = 0;//文件类型73             }74 75             fwrite(&fileInDir, sizeof(fileInDir), 1, wfp); //将子目录信息写入打包文件76             cout << "subname:" << fileInDir.FolderName << ",nameLen:" << fileInDir.FolderNameLen << ",path:" << fileInDir.Filepath << ",size:" << fileInDir.FileSize << ",type:" << fileInDir.type << endl;77 78             FILE *Files = fopen((*newIt).c_str(), "rb");79 80             if (fileInDir.type == 0)81             {82                 eachFile = new unsigned char[fileInDir.FileSize];83                 folderBuffer.push_back(eachFile); //定义全局变量:unsigned char *eachFile;以及文件夹缓冲区vector<unsigned char *>folderBuffer; 84 85 86                 fread(folderBuffer[j], fileInDir.FileSize, 1, Files);87 88                 fwrite(folderBuffer[j], fileInDir.FileSize, 1, wfp);89                 j++;90             }91             else92             {93                 continue;94             }        
95         }96         cout << endl;97     }

复制代码

 别忘记咱们的打包函数接口设计的是:bool PackFileAndDirectory(const vector<string>& files, const vector<string>& directories, const string& outputfilename)

  哎呦,写博客不仅让我回温了一遍自己的思路、把代码整理好,还让我觉得一个好的程序员不光是撸代码还可以写文章,哈哈,小女子才疏学浅,愿各路大神赐教,下一篇咱们解包干起来!!

原文出处:https://www.cnblogs.com/liuxuemei/p/9491622.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP