文件(含多级子目录)的打包和解包(下)

本文详细介绍了如何解包一个.dat文件,包括文件和文件夹的解包过程,并提供了具体的C++代码实现。同时讨论了解包过程中使用缓冲区的原因及如何避免内存泄漏。

  现在咱们说说解包,一个.dat文件,里面不知道包含了多少个文件/文件夹的信息,我们怎么解包呢?又怎么保证文件与文件之间、文件与其子文件之间的分级对应关系呢?下面我们来回顾一下打包的过程:把文件/文件夹的外部信息(文件名、文件名长度、文件的长度)/(文件夹名、文件夹名长度、文件的长度、文件的相对路径信息、文件类型)以结构体的形式存放在.dat文件中,内容也保存到.dat文件中

  解包参数设置: bool UnPackFileAndDirectory(const string& inputzipfile, const string& outputpath)

         其中第一个参数inputzipfile是要解包哪个文件(全路径),第二个参数outputpath是解包在哪一路径下(给定路径)

  解包按照打包接口逻辑的话:文件、文件夹的顺序读取内容即可,当然啦,两边的结构体信息要定义相同,这样大家的协议就一样,解包便不会出现问题了。

  解包流程:1.定位解包文件;2.解包文件部分(文件外部信息+文件内容),写入到指定路径下;3.解包文件夹部分(文件夹外部信息,没有内容哈,文件夹的内容为0),创建文件夹,并建立在指定路径下

 1 bool UnPackFileAndDirectory(const string& inputzipfile, const string& outputpath) 
 2 {
 3     FILE *rfp = NULL;
 4     rfp = fopen(inputzipfile.c_str(), "rb");
 5     if (rfp == NULL)
 6     {
 7         cout << "解包:文件打开失败!" << endl;
 8         return false;
 9     }
10 
11     //文件部分
12     int filecount;
13     fread(&filecount, sizeof(filecount), 1, rfp);
14     
15     for (size_t i = 0; i < filecount; i++)
16     {
17         struct FileInfo packFile;
18         fread(&packFile, sizeof(packFile), 1, rfp);
19 
20         cout << "filename:" << packFile.FileName << ", nameLen:" << packFile.fileNameLen << ", fileLen:" << packFile.fileSize << endl;
21         string path_file = outputpath + '\\' + packFile.FileName; //path_file:全路径
22 
23         FILE *unpackFile = NULL;
24         unpackFile = fopen(path_file.c_str(), "wb");
25         if (unpackFile == NULL)
26         {
27             cout << "文件:文件创建失败!" << endl;
28         }
29 
30         unsigned char*tmpBu = new unsigned char[packFile.fileSize];
31         fread(tmpBu, packFile.fileSize, 1, rfp);//当然也可以不借助缓冲区
32         fwrite(tmpBu, packFile.fileSize, 1, unpackFile);
33 
34     }
35     cout << endl;
36 
37     //文件夹部分
38     int folderCount;
39     fread(&folderCount, sizeof(folderCount), 1, rfp);
40 
41     for (size_t i = 0; i < folderCount; i++)
42     {
43         struct FolderInfo folder;
44         fread(&folder, sizeof(folder), 1, rfp);
45 
46         //文件夹的基本信息
47         cout << "FolderName:" << folder.FolderName << ", nameLen:" << folder.FolderNameLen << ", FolderSize:" << folder.FileSize << ", path:" << folder.Filepath << ", type:" << folder.type << endl;
48 
49         string path_folder = outputpath + '\\' + folder.Filepath; //解包后全路径
50         const char * Lpath = path_folder.c_str();
51 
52         if (folder.type == 0 ) //文件类型
53         {
54             FILE * unpackFolders = NULL;
55             unpackFolders = fopen(path_folder.c_str(), "wb");
56             if (unpackFolders == NULL)
57             {
58                 cout << "文件夹:子文件创建失败!" << endl;
59             }
60 
61             unsigned char*readFolder = new unsigned char[folder.FileSize];
62             fread(readFolder, folder.FileSize, 1, rfp);
63             fwrite(readFolder, folder.FileSize, 1, unpackFolders);
64 
65         }
66         if (folder.type == 1)//文件夹类型
67         {
68             ::CreateDirectory(Lpath, NULL); //创建文件夹
69         }
70     }
71 
72     return true;
73 }

  细心的小伙伴都发现了,我在文件解包和打包的过程中,都用到了临时的缓冲区:unsigned char*tmpBu = new unsigned char[fileSize];我为什么不直接从一个文件读再写入目标文件呢?主要是我之前就是那么干的,结果发现有的文件解包出来与原来的文件并不一致。我用的对比软件是BeyongCompare 4,这个软件是我直属领导安利的,可以对比两个文件/文件夹是否一样,而且任何格式的都可以,这样的软件对我来说简直就是黑科技,amazing~

  我想请教各位C++大神,如何不借助缓冲区,实现咱们这个功能呢?

  -------------------------------------------------------------(分割线)------------------------------------------------------------------------------------------------------

  之前有位大神在我博文下评论,说我new的空间没有释放(造成内存泄漏),get到了,大家不要跟我一样粗心哦~

  文件打包解包这一专题终于写完了,好开心呀。有需要改进完善的地方欢迎大家提出宝贵意见,膜拜各位大佬 ...

 

转载于:https://www.cnblogs.com/liuxuemei/p/9498153.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值