2009-12-18 70 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库。