2009-12-18 15 views

risposta

7

A partire da iOS8/OSX10.10 esiste un modo integrato per creare archivi zip utilizzando NSFileCoordinatorReadingOptions.ForUploading. Un semplice esempio di creare archivi zip senza dipendenze non cacao:

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

Questo è grandioso, ma per quanto riguarda il contrario? Cioè, avendo un file zip e quindi leggendo il suo contenuto come se fosse una directory? – adib

+1

Ho cercato ma non ho trovato alcun metodo simile per andare al contrario. Ho votato questa risposta perché è sorprendente. Tuttavia, nella mia app Mac, ho invece usato NSTask per richiamare/usr/bin/zip e/usr/bin/unzip. È semplice, offre molte * opzioni * documentate per controllare il comportamento, e nel mio caso ha preso meno codice di questo. –

9
+0

ZipKit sembra denominare meglio i suoi metodi di ZipArchive (anche se non capisco il motivo per cui prefissi i suoi metodi di addizione). – kiamlaluno

+0

I metodi di prefisso o suffisso della categoria aiutano a evitare conflitti di nome se Apple aggiunge un metodo in Cocoa con lo stesso nome. –

+1

ZipKit è ora disponibile all'indirizzo https://github.com/kolpanic/ZipKit e non più su bitbucket (shock) – uchuugaka

11

Oltre a leggere e scrivere archivi zip nel proprio processo, non c'è motivo di vergognarsi nell'usare NSTask per eseguire zip e unzip.

+0

L'utilizzo di questo metodo consente di non modificare il codice per supportare nuove funzionalità. Mi chiedo che cosa esattamente Finder quando si seleziona un file/directory e quindi selezionare "Comprimi" dal menu. Quale eseguibile utilizza Finder? – kiamlaluno

+0

Utilizza l'utilità di archiviazione. –

0

Partenza zipzap, il mio digiuno file zip libreria di I/O.

Problemi correlati