引自 http://www.36duo.com/thread-119-1-1.html
在本教程中,我將演示如何在iOS程序中壓縮和解壓縮文件。我們將使用一個叫做ZipArchive的第三方庫來實現。盡管壓縮和解壓縮有許多其他的方案可選,但是我覺得ZipArchive庫是最快捷、最簡單的解決方案。let’s go。
為什么我需要解壓縮文件
有許多原因能解釋為什么我要在工程中使用壓縮和解壓縮功能,下面是幾個常見的原因:
蘋果App Store的50M下載限制
蘋 果公司出於流量的考慮,規定在非WIFI環境下,限制用戶只能下載小於50M的應用或游戲。這樣一來,對於一些數據或數據包較大的應用,我們只能盡量減小 應用二進制包的體積。而把數據打包到zip中,這樣App可以通過網絡下載數據包,解壓出所需要的內容,而且這樣也可以動態的更新內容。
動態更新內容
這 一點在上面已經提過了。如果應用所需要的資源需要動態更新,一種常見的做法是更新資源,重新打包,重新提交到App store,這樣做你需要等待漫長的審核、上架時間。一般情況下是一周左右的時間。更好的方法是將這些資源打包放置在服務器上,App從服務器(或者雲存 儲)上下載,然后解壓。這樣做的好處顯而易見,那就是可以快速更新,動態更新,不需要重新打包、上傳、審核,省時省力。
從Web上下載zip文件
Safari和郵件程序都不支持zip的查看,通過ZipArchive你就可以為你的設備增加查看zip文件的能力了,盡管App Store里已經有一些App支持這些功能了。
工程設置
首先從google code上check out一份代碼,svn地址是:http://ziparchive.googlecode.com/svn/trunk/ziparchive-read-only
在終端中輸入如下命令即可check out了:
svn co http://ziparchive.googlecode.com/svn/trunk/ziparchive-read-only
或者直接從http://ziparchive.googlecode.com/files/ZipArchive.zip 下載。
把minizip文件夾和ZipArchive.h以及ZipArchive.mm文件添加到你的工程中。
因為ZipArchive不支持ARC,所以如果你的工程開啟了ARC,那么就需要對ZipArchive設置一下。在ZipArchive.mm編譯選項中,增加-fno-objc-arc即可。
最后,需要為工程鏈接libz動態鏈接庫。
至此,ZipArchive已經集成到你的工程中了,編譯工程,應該可以編譯成功。可能會有一些警告,這無關緊要,不影響編譯。但是作為一個態度嚴謹的程序員,我強烈建議你看一下這些警告是怎么出現的,解決它們。請記住:在你的工程中,警告應該和錯誤一樣被嚴肅處理!
下載和解壓縮文件
接 下來就向大家展示在你的工程中如何從網上下載zip文件,解壓縮,並讀取zip壓縮包中的文件內容。處於演示考慮,主要的目的是向大家演示 ZipArchive接口的使用方法,所以代碼的錯誤處理和條件檢查並沒有做過多的考量,在實際的工程中,還是需要大家自己做更為嚴格的條件檢查和錯誤處 理工作。
示例工程的運行效果如下圖:
工 程中只是在ViewController中增加了一個UIImageView和一個UILabel。我們將從網絡上下載zip文件,zip文件中包含一張 圖片和一個文本文件。下載解壓后,圖像會被渲染到UIImageView中,而文本會作為UILabel的內容展示。示例代碼在文章末尾。希望讀者朋友們 自行下載,編譯,查看效果。
好,接下來講一講具體的實現:
1.引入ZipArchive的頭文件。
- #import "ZipArchive.h"
2.下載zip文件
- dispatch_queue_t queue = dispatch_get_global_queue(
- DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_async(queue, ^{
- NSURL *url = [NSURL URLWithString:@"http://www.icodeblog.com/wp-content/uploads/2012/08/zipfile.zip"];
- NSError *error = nil;
- NSData *data = [NSData dataWithContentsOfURL:url options:0 error:&error];
- if(!error)
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
- NSString *path = [paths objectAtIndex:0];
- NSString *zipPath = [path stringByAppendingPathComponent:@"zipfile.zip"];
- [data writeToFile:zipPath options:0 error:&error];
- if(!error)
- // TODO: Unzip
- NSLog(@"Error saving file %@",error);
- NSLog(@"Error downloading zip file: %@", error);
上面這段代碼的主要作用就是從iCodeBlog上下載一個zip文件,並寫入到應用的緩存目錄中。
現在zip文件已經下載下來了,接下來就是要解壓縮,並將解壓縮出來的文件利用起來。
3. 解壓縮已下載的zip文件
在第二步中,我們已經把zip文件下載到/Library/Caches/zipfile.zip,現在來解壓縮。
把上面代碼中的//TODO: Unzip用下面的代碼替換掉。
- ZipArchive *za = [[ZipArchive alloc] init];
- if ([za UnzipOpenFile: zipPath]) {
- BOOL ret = [za UnzipFileTo: path overWrite: YES];
- if (NO == ret){} [za UnzipCloseFile];
- NSString *imageFilePath = [path stringByAppendingPathComponent:@"photo.png"];
- NSString *textFilePath = [path stringByAppendingPathComponent:@"text.txt"];
- NSData *imageData = [NSData dataWithContentsOfFile:imageFilePath options:0 error:nil];
- UIImage *img = [UIImage imageWithData:imageData];
- NSString *textString = [NSString stringWithContentsOfFile:textFilePath
- encoding:NSASCIIStringEncoding error:nil];
- dispatch_async(dispatch_get_main_queue(), ^{
- self.imageView.image = img;
- self.label.text = textString;
對上面的代碼做一個簡單的解釋:
1. 在內存中解壓縮文件
2. 將解壓縮的內容寫到緩存目錄中
3. 使用解壓縮后的文件
4. 更新UI
非常簡單吧!
壓縮文件
接下來看一下怎么進行文件壓縮。在上面的步驟中,我們已經把一個zip文件解壓縮到緩存目錄中。現在我們再把解壓縮出來的文件重新壓縮為一個zip文件,並把這個zip文件寫入到Documents目錄里去(OMG,這兩個文件太慘了,被反復蹂躪)
在示例工程代碼中,我已經增加了一個按鈕,並和一個IBAction相關聯,按鈕的處理函數名為zipFilesBUttonPressed:,具體代碼如下:
- - (IBAction)zipFilesButtonPressed:(id)sender
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *docspath = [paths objectAtIndex:0];
- paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
- NSString *cachePath = [paths objectAtIndex:0];
- NSString *zipFile = [docspath stringByAppendingPathComponent:@"newzipfile.zip"];
- ZipArchive *za = [[ZipArchive alloc] init];
- [za CreateZipFile2:zipFile];
- NSString *imagePath = [cachePath stringByAppendingPathComponent:@"photo.png"];
- NSString *textPath = [cachePath stringByAppendingPathComponent:@"text.txt"];
- [za addFileToZip:imagePath newname:@"NewPhotoName.png"];
- [za addFileToZip:textPath newname:@"NewTextName.txt"];
- BOOL success = [za CloseZipFile2];
- NSLog(@"Zipped file with result %d",success);
簡單解釋一下上面代碼的意思:
1. 獲取Documents目錄,新的zip文件要寫入到這個目錄里。
2. 獲取Caches目錄,要進行壓縮的文件在這個目錄里。
3. 獲取zip文件的全路徑名。
4. 創建一個ZipArchive實例,並創建一個內存中的zip文件。需要注意的是,只有當你調用了CloseZipFile2方法之后,zip文件才會從內存中寫入到磁盤中去。
5. 獲取要被壓縮的文件的全路徑
6. 把要壓縮的文件加入到zip對象中去,加入的文件數量沒有限制,也可以加入文件夾到zip對象中去。
7. 把zip從內存中寫入到磁盤中去。
當點擊按鈕之后,在應用的Documents文件夾下應該有一個叫newzipfile.zip的文件。解壓這個文件,就能解壓出那兩個被反復蹂躪的文件來
結論
現在你知道如何使用ZipArchive來壓縮和解壓縮文件了。享受ZipArchive的便利吧。示例工程已經很好的展示了這些基本用法,大家可以好好研究下。