2009-12-18 22 views

Respuesta

7

A partir de iOS8/OSX10.10 hay una forma incorporada para crear archivos comprimidos usando NSFileCoordinatorReadingOptions.ForUploading. Un ejemplo simple de crear archivos zip sin ningún tipo de dependencias no 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

Esto es genial, pero ¿qué pasa al revés? Es decir, tener un archivo comprimido y luego leer su contenido como si fuera un directorio. – adib

+1

Miré pero no pude encontrar ningún método similar para ir al revés. He votado esta respuesta porque es increíble. Sin embargo, en mi aplicación Mac, en su lugar, utilicé NSTask para invocar/usr/bin/zip y/usr/bin/unzip. Es sencillo, ofrece muchas opciones * documentadas * para controlar el comportamiento, y en mi caso tomó menos código que este. –

9
+0

ZipKit parece nombrar mejor a sus métodos que ZipArchive (aunque no entiendo por qué prefijos sus métodos de adición). – kiamlaluno

+0

Los métodos de categorías prefijados o sufijos ayudan a evitar colisiones de nombres si Apple alguna vez agrega un método en Cocoa con el mismo nombre. –

+1

ZipKit está ahora en https://github.com/kolpanic/ZipKit y ya no está en bitbucket (shocker) – uchuugaka

11

Además de leer y escribir archivos comprimidos en su propio proceso, no es ninguna pena utilizar NSTask para ejecutar zip y unzip.

+0

El uso de este método permitiría no cambiar el código para admitir nuevas características. Me pregunto qué encontrará exactamente Finder cuando seleccione un archivo/directorio, y luego seleccione "Comprimir" en el menú. ¿Qué ejecutable usa Finder? – kiamlaluno

+0

Utiliza Archive Utility. –

0

Salida zipzap, mi ayuno archivo zip biblioteca de E/S.

Cuestiones relacionadas