2009-12-18 73 views

回答

7

從iOS8/OSX10.10開始,有一種使用NSFileCoordinatorReadingOptions.ForUploading創建zip檔案的內置方法。一個簡單的例子創建ZIP檔案沒有任何非可可的依賴關係:

public extension NSURL { 

    /// Creates a zip archive of the file/folder represented by this URL and returns a references to the zipped file 
    /// 
    /// - parameter dest: the destination URL; if nil, the destination will be this URL with ".zip" appended 
    func zip(dest: NSURL? = nil) throws -> NSURL { 
     let destURL = dest ?? self.URLByAppendingPathExtension("zip") 

     let fm = NSFileManager.defaultManager() 
     var isDir: ObjCBool = false 

     let srcDir: NSURL 
     let srcDirIsTemporary: Bool 
     if let path = self.path where self.fileURL && fm.fileExistsAtPath(path, isDirectory: &isDir) && isDir.boolValue == true { 
      // this URL is a directory: just zip it in-place 
      srcDir = self 
      srcDirIsTemporary = false 
     } else { 
      // otherwise we need to copy the simple file to a temporary directory in order for 
      // NSFileCoordinatorReadingOptions.ForUploading to actually zip it up 
      srcDir = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(NSUUID().UUIDString) 
      try fm.createDirectoryAtURL(srcDir, withIntermediateDirectories: true, attributes: nil) 
      let tmpURL = srcDir.URLByAppendingPathComponent(self.lastPathComponent ?? "file") 
      try fm.copyItemAtURL(self, toURL: tmpURL) 
      srcDirIsTemporary = true 
     } 

     let coord = NSFileCoordinator() 
     var error: NSError? 

     // coordinateReadingItemAtURL is invoked synchronously, but the passed in zippedURL is only valid 
     // for the duration of the block, so it needs to be copied out 
     coord.coordinateReadingItemAtURL(srcDir, options: NSFileCoordinatorReadingOptions.ForUploading, error: &error) { (zippedURL: NSURL) -> Void in 
      do { 
       try fm.copyItemAtURL(zippedURL, toURL: destURL) 
      } catch let err { 
       error = err as NSError 
      } 
     } 

     if srcDirIsTemporary { try fm.removeItemAtURL(srcDir) } 
     if let error = error { throw error } 
     return destURL 
    } 
} 

public extension NSData { 
    /// Creates a zip archive of this data via a temporary file and returns the zipped contents 
    func zip() throws -> NSData { 
     let tmpURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(NSUUID().UUIDString) 
     try self.writeToURL(tmpURL, options: NSDataWritingOptions.DataWritingAtomic) 
     let zipURL = try tmpURL.zip() 
     let fm = NSFileManager.defaultManager() 
     let zippedData = try NSData(contentsOfURL: zipURL, options: NSDataReadingOptions()) 
     try fm.removeItemAtURL(tmpURL) // clean up 
     try fm.removeItemAtURL(zipURL) 
     return zippedData 
    } 
} 
+0

這很好,但是反過來呢?也就是說,有一個zip文件,然後閱讀它的內容,就好像它是一個目錄? – adib 2015-12-31 04:47:41

+1

我看起來,但找不到任何類似的方法去其他方式。我已經投票贊成這個答案,因爲它太棒了。但是,在我的Mac應用程序中,我使用NSTask來調用/ usr/bin/zip和/ usr/bin/unzip。它很簡單,提供了很多*記錄的*選項來控制行爲,在我的情況下,代碼比這少。 – 2016-02-26 14:20:51

9
+0

ZipKit似乎更好的名字它的方法比ZipArchive(即使我不明白爲什麼它的前綴的另外的方法)。 – kiamlaluno 2009-12-18 13:52:54

+0

前綴或後綴類別方法有助於避免名稱衝突,如果蘋果在Cocoa中添加同名方法。 – 2009-12-19 07:17:25

+1

ZipKit現在位於https://github.com/kolpanic/ZipKit,不再位於bitbucket(令人震驚) – uchuugaka 2013-10-17 00:58:02

11

除了在您自己的過程中閱讀和編寫zip歸檔文件,使用NSTask運行zipunzip並不是件恥辱。

+0

使用此方法將允許不更改代碼以支持新功能。我不知道當你選擇一個文件/目錄時,Finder究竟發生了什麼,然後從菜單中選擇「壓縮」。 Finder使用哪個可執行文件? – kiamlaluno 2009-12-19 06:59:03

+0

它使用存檔實用程序。 – 2009-12-19 07:16:22

0

退房zipzap,我快zip文件I/O庫。