工作中有需要使用到壓縮與解壓縮 zip 檔案,原本 Mac 以為內建的壓縮功能就可以做到,如下:
https://developer.apple.com/documentation/compression
結果試了半天,也查了一堆資料,好像都無法做到。在查詢資料的過程中,也看到很多人推薦 ZipArchive,我也就用它來測試了。
https://github.com/ZipArchive/ZipArchive
ZipArchive 是 Objective-C 寫的專案,我是要用 Swift 去執行,底下記錄了詳細過程。如果對於 Swift 連結 Objective-C 想多了解一點,可參考這篇:Swift 連結 Swift、Objective-C、C++
ZipArchive 的 Github 專案上有教導如何安裝使用,因為我沒有使用其他安裝工具,所以我採取手動安裝,它主要方法有四:
-
Add the SSZipArchive and minizip folders to your project.
-
Add the libz and libiconv libraries to your target.
-
Add the Security framework to your target.
-
Add the following GCC_PREPROCESSOR_DEFINITIONS: HAVE_INTTYPES_H HAVE_PKCRYPT HAVE_STDINT_H HAVE_WZAES HAVE_ZLIB $(inherited).
底下逐一記錄過程。
1. 將 SSZipArchive and minizip 加入專案
先建一個 unzip 專案,使用主功能表 File -> Add Files to "unzip"...
採用 Create groups 的方式把 SSZipArchive 包括 minizip 都加入專案中。
加入後會在專案中看到如下結構。
2. 把 libz 和 libiconv 庫加入目標
如下圖,把 libz 和 libiconv 加入。
3. 把 Security 框架加入目標
方法同上,結果如下圖:
完成後也會在左邊的專案看到剛加入的程式庫及框架。
4. 設定 Preprocessor
如下圖,在 Target 的 Build Settings 搜尋 Prepor 可以很快找到 Preprocessor Macros,並填入
HAVE_INTTYPES_H HAVE_PKCRYPT HAVE_STDINT_H HAVE_WZAES HAVE_ZLIB $(inherited)
這個步驟由原始的說明也是看不懂如何做,後來查了其他網頁的說明才知道操作方法。
產生 unzip-Bridging-Header.h
因為 ZipArchive 是 Objective-C 所寫的專案,所以需要利用 unzip-Bridging-Header.h 的檔頭來連結。
先建立空白的 .h 檔案,檔名必須是 "專案名稱-Bridging-Header.h",內容只要一行:
#import "ZipArchive.h"
通常如果連結 Objective-C 的檔案,會詢問要不要自動加入 "專案名稱-Bridging-Header.h" 的檔案,若是自己產生,要記得檢查有沒有設定?若沒有就要自己加上去。
如下圖,在 Build Settings 找到 Swift Compiler-General 的 Objective-C Bridging Header,填入 unzip/unzip-Bridging-Header.h 就可以了。
unzip 要記得改成自己的專案名。
壓縮/解壓縮程式
最後來寫測試用的程式,這是一個單純把 test.zip 解壓縮到桌面的 unzip 目錄中。
@IBAction func btUnzip(_ sender: Any) {
let source = "/Users/heaven/Desktop/test.zip"
let destination = "/Users/heaven/Desktop/output"
let unZipOK = SSZipArchive.unzipFile(atPath: source, toDestination: destination)
print(unZipOK)
}
測試結果成功。
如果失敗,記得檢查是不是沙箱限制了檔案的讀寫。
不過中文的目錄解出來一開始亂碼,後來在 Windows 壓縮中文的檔名時,用 Bandizip 並把設定中紅框處也打勾,程式中解出來的就沒有問題了。不過在沒有打勾的情況下,mac 系統本身的解壓縮倒也可以順利解出中文目錄名。
底下再簡單列一下壓縮和解壓縮的方法:
壓縮多檔:
SSZipArchive.createZipFile(atPath: "output.zip", withFilesAtPaths: ["/dir1/file1","/dir2/file2.txt"])
壓縮目錄:
SSZipArchive.createZipFile(atPath: "output.zip", withContentsOfDirectory: "/dir/dir")
解壓縮:
SSZipArchive.unzipFile(atPath: "source.zip", toDestination: "/outputdir")
其實 ZipArchive 功能不少,也支援密碼,詳細可看原專案中的範例或上網搜尋。
這裡有一段 OC 的程式碼,看來是一邊解壓縮一邊印出記錄,暫時不研究,先貼上程式碼:
https://nintendoboy.gitbooks.io/objectivec-study-note-v2/ziparchive.html
// 解壓壓縮包至某路徑,並且可以監測解壓的實時情況
[SSZipArchive unzipFileAtPath:@"/Users/zhangfan/Desktop/images.zip" toDestination:@"/Users/zhangfan/Desktop/images" progressHandler:^(NSString *entry, unz_file_info zipInfo, long entryNumber, long total) {
NSLog(@"正在解壓第:%ld 個文件,總共 %ld個文件",entryNumber,total);
} completionHandler:^(NSString *path, BOOL succeeded, NSError *error) {
NSLog(@"解壓文件到路徑:%@,是否成功:%d",path,succeeded);
}];
/*
2016-12-14 14:46:12.832 zipTest[2170:67758] 正在解壓第:1 個文件,總共 2個文件
2016-12-14 14:46:12.987 zipTest[2170:67758] 正在解壓第:2 個文件,總共 2個文件
2016-12-14 14:46:12.988 zipTest[2170:67758] 解壓文件到路徑:/Users/zhangfan/Desktop/images.zip,是否成功:1
*/
- 瀏覽次數:12465
發表新回應