Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a ZIP archive from a Cocoa application

Are there Objective-C classes that are equivalent to the ones contained in the Java package java.util.zip?
Is to execute a CLI command the only alternative?

like image 321
apaderno Avatar asked Dec 18 '09 13:12

apaderno


People also ask

How do I create an archive zip file?

To zip (compress) a file or folder Locate the file or folder that you want to zip. Press and hold (or right-click) the file or folder, select (or point to) Send to, and then select Compressed (zipped) folder. A new zipped folder with the same name is created in the same location.

What is the difference between zip and archive?

Key Difference: ZIP is a format used to compress and archive a file. Whereas, archive is the process where one or more computer files along with the metadata are composed to make a single file.

What is an archive zip folder?

ZIP is an archive file format that supports lossless data compression. A ZIP file may contain one or more files or directories that may have been compressed. The ZIP file format permits a number of compression algorithms, though DEFLATE is the most common.


3 Answers

As of iOS8/OSX10.10 there is a built-in way to create zip archives using NSFileCoordinatorReadingOptions.ForUploading. A simple example of create zip archives without any non-Cocoa dependencies:

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
    }
}
like image 187
marcprux Avatar answered Sep 19 '22 04:09

marcprux


Aside from reading and writing zip archives in your own process, there's no shame in using NSTask to run zip and unzip.

like image 38
Peter Hosey Avatar answered Sep 19 '22 04:09

Peter Hosey


  • There is a zip-framework, http://code.google.com/p/zip-framework/, but it seems to be in an early (version 0.1) stage.

  • Others answers on cocoadev: http://cocoadev.com/ZipArchiveLibraryForCocoa

  • One answer from there: ZipKit, https://github.com/kolpanic/ZipKit

like image 42
miku Avatar answered Sep 19 '22 04:09

miku