2009-12-18 11 views

Odpowiedz

7

Od wersji iOS8/OSX10.10 istnieje wbudowany sposób tworzenia archiwów zip przy użyciu NSFileCoordinatorReadingOptions.ForUploading. Prostym przykładem tworzyć archiwa ZIP bez żadnych zależności zakaz kakao:

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

To jest świetne, ale co z tym na odwrót? To znaczy, mając plik zip, a następnie czytając jego zawartość tak, jakby był katalogiem? – adib

+1

Wyglądałem, ale nie mogłem znaleźć żadnej podobnej metody, aby przejść na drugą stronę. Głosowałem za tą odpowiedzią, ponieważ jest niesamowita. Jednak w mojej aplikacji na Macu użyłem NSTask do wywołania/usr/bin/zip i/usr/bin/unzip. Jest to proste, oferuje wiele * udokumentowanych * opcji kontrolowania zachowania, aw moim przypadku miało mniej kodu niż ten. –

9
+0

ZipKit wydaje się lepiej wymienić swoje metody niż ZipArchive (nawet jeśli nie rozumiem, dlaczego to poprzedza jego metody dodatkowo). – kiamlaluno

+0

Metody określania prefiksów lub sufiksów pomagają uniknąć kolizji nazw, jeśli Apple kiedykolwiek doda metodę w Cocoa pod tą samą nazwą. –

+1

ZipKit jest teraz na https://github.com/kolpanic/ZipKit i nie jest już na bitbucket (shocker) – uchuugaka

11

Oprócz czytania i zapisywania archiwów zip w swoim procesie, nie ma wstydu używać NSTask do uruchamiania zip i unzip.

+0

Użycie tej metody pozwoliłoby na niezmienianie kodu w celu obsługi nowych funkcji. Zastanawiam się, co dokładnie robi Finder po wybraniu pliku/katalogu, a następnie wybierz "Kompresuj" z menu. Z jakiego pliku wykonywalnego korzysta Finder? – kiamlaluno

+0

Używa narzędzia Archive Utility. –

0

Wyjazd zipzap, mój szybki plik zip I/O biblioteki.

Powiązane problemy