Swift 使用 ZipArchive 解/壓縮檔案

工作中有需要使用到壓縮與解壓縮 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 專案上有教導如何安裝使用,因為我沒有使用其他安裝工具,所以我採取手動安裝,它主要方法有四:

  1. Add the SSZipArchive and minizip folders to your project.

  2. Add the libz and libiconv libraries to your target.

  3. Add the Security framework to your target.

  4. 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 都加入專案中。

 

image

 

加入後會在專案中看到如下結構。

 

image

 

2. 把 libz 和 libiconv 庫加入目標

 

如下圖,把 libz 和 libiconv 加入。

 

image

 

3. 把 Security 框架加入目標

 

方法同上,結果如下圖:

 

image

 

完成後也會在左邊的專案看到剛加入的程式庫及框架。

 

image

 

4. 設定 Preprocessor

 

如下圖,在 Target 的 Build Settings 搜尋 Prepor 可以很快找到 Preprocessor Macros,並填入

 

HAVE_INTTYPES_H HAVE_PKCRYPT HAVE_STDINT_H HAVE_WZAES HAVE_ZLIB $(inherited)

 

這個步驟由原始的說明也是看不懂如何做,後來查了其他網頁的說明才知道操作方法。

 

image

 

產生 unzip-Bridging-Header.h

 

因為 ZipArchive 是 Objective-C 所寫的專案,所以需要利用 unzip-Bridging-Header.h 的檔頭來連結。

 

先建立空白的 .h 檔案,檔名必須是 "專案名稱-Bridging-Header.h",內容只要一行:

 

#import "ZipArchive.h"

 

image

 

通常如果連結 Objective-C 的檔案,會詢問要不要自動加入 "專案名稱-Bridging-Header.h" 的檔案,若是自己產生,要記得檢查有沒有設定?若沒有就要自己加上去。

 

如下圖,在 Build Settings 找到 Swift Compiler-General 的 Objective-C Bridging Header,填入 unzip/unzip-Bridging-Header.h 就可以了。

 

unzip 要記得改成自己的專案名。

 

image

 

壓縮/解壓縮程式

 

最後來寫測試用的程式,這是一個單純把 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)

}

 

測試結果成功。

 

如果失敗,記得檢查是不是沙箱限制了檔案的讀寫。

 

image

 

不過中文的目錄解出來一開始亂碼,後來在 Windows 壓縮中文的檔名時,用 Bandizip 並把設定中紅框處也打勾,程式中解出來的就沒有問題了。不過在沒有打勾的情況下,mac 系統本身的解壓縮倒也可以順利解出中文目錄名。

 

image

 

底下再簡單列一下壓縮和解壓縮的方法:

 

壓縮多檔:

 

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

*/

 

重要度:

發表新回應

借我放一下廣告