文件(含多級子目錄)的打包和解包(中)


  上次博文說到了文件的打包,這次咱們來說一說文件夾的打包。

  要打包的文件夾可能有很多,單個文件夾的子目錄也未知,所以需要逐一遍歷文件夾的所有子目錄!這個接口大家應該已經知道了(還不知道的,快去pick我的上篇博文O(∩_∩)O~) 程序員必備:思路清晰,那我就假裝是一名合格的程序媛,故千辛萬苦畫了一張圖,更直接明了地表達下我的觀點和做法:

  

 

 

 

 

 

 

 

 

 

 

 

  要打包的文件夾: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             else
71             {
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             else
92             {
93                 continue;
94             }        
95         }
96         cout << endl;
97     }

 別忘記咱們的打包函數接口設計的是:bool PackFileAndDirectory(const vector<string>& files, const vector<string>& directories, const string& outputfilename)

  哎呦,寫博客不僅讓我回溫了一遍自己的思路、把代碼整理好,還讓我覺得一個好的程序員不光是擼代碼還可以寫文章,哈哈,小女子才疏學淺,願各路大神賜教,下一篇咱們解包干起來!!

 

 

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM