Swift的ZIP处理 – ZIPFoundation

weixin_38112450 2019-09-12 12:10:27
ZIP Foundation is a library to create, read and modify ZIP archive files. Features Modern Swift API High Performance Compression and Decompression Deterministic Memory Consumption Linux compatibility No 3rd party dependencies (on Apple platforms, zlib on Linux) Comprehensive Unit and Performance Test Coverage Complete Documentation Requirements iOS 9.0+ / macOS 10.11+ / tvOS 9.0+ / watchOS 2.0+ Or Linux with zlib development package Xcode 9.0 Swift 4.0 Installation Swift Package Manager Swift Package Manager is a dependency manager currently under active development. To learn how to use the Swift Package Manager for your project, please read the official documentation . The ZIP Foundation package uses the V4 Package Description API . To add ZIP Foundation as a dependency, you have to add it to thedependenciesof yourPackage.swiftfile and refer to that dependency in yourtarget. import PackageDescription let package = Package( name: "<Your Product Name>", dependencies: [ .package(url: "https://github.com/weichsel/ZIPFoundation/", .upToNextMajor(from: "0.9.0")) ], targets: [ .target( name: "<Your Target Name>", dependencies: ["ZIPFoundation"]), ] ) After adding the dependency, you can fetch the library with: $ swift package resolve CocoaPods CocoaPods is a dependency manager for Objective-C and Swift. To learn more about setting up your project for CocoaPods, please refer to the official documentation . To integrate ZIP Foundation into your Xcode project using CocoaPods, you have to add it to your project’sPodfile: source 'https://github.com/CocoaPods/Specs.git' platform :ios, '10.0' use_frameworks! target '<Your Target Name>' do pod 'ZIPFoundation', '~> 0.9' end Afterwards, run the following command: $ pod install Usage ZIP Foundation provides two high level methods to zip and unzip items. Both are implemented as extension ofFileManager. The functionality of those methods is modeled after the behavior of the Archive Utility in macOS. Zipping Files and Directories To zip a single file you simply pass a file URL representing the item you want to zip and a destination URL toFileManager.zipItem(at sourceURL: URL, to destinationURL: URL): let fileManager = FileManager() let currentWorkingPath = fileManager.currentDirectoryPath var sourceURL = URL(fileURLWithPath: currentWorkingPath) sourceURL.appendPathComponent("file.txt") var destinationURL = URL(fileURLWithPath: currentWorkingPath) destinationURL.appendPathComponent("archive.zip") do { try fileManager.zipItem(at: sourceURL, to: destinationURL) } catch { print("Creation of ZIP archive failed with error:\(error)") } The same method also accepts URLs that represent directory items. In that case,zipItemadds the directory content ofsourceURLto the archive. By default, a root directory entry named after thelastPathComponentof thesourceURLis added to the destination archive. If you don’t want to preserve the parent directory of the source in your archive, you can passshouldKeepParent: false. Unzipping Archives To unzip existing archives, you can useFileManager.unzipItem(at sourceURL: URL, to destinationURL: URL). This recursively extracts all entries within the archive to the destination URL: let fileManager = FileManager() let currentWorkingPath = fileManager.currentDirectoryPath var sourceURL = URL(fileURLWithPath: currentWorkingPath) sourceURL.appendPathComponent("archive.zip") var destinationURL = URL(fileURLWithPath: currentWorkingPath) destinationURL.appendPathComponent("directory") do { try fileManager.createDirectory(at: destinationURL, withIntermediateDirectories: true, attributes: nil) try fileManager.unzipItem(at: sourceURL, to: destinationURL) } catch { print("Extraction of ZIP archive failed with error:\(error)") } Advanced Usage ZIP Foundation also allows you to individually access specific entries without the need to extract the whole archive. Additionally it comes with the ability to incrementally update archive contents. Accessing individual Entries To gain access to specific ZIP entries, you have to initialize anArchiveobject with a file URL that represents an existing archive. After doing that, entries can be retrieved via their relative path.Archiveconforms toSequenceand therefore supports subscripting: let fileManager = FileManager() let currentWorkingPath = fileManager.currentDirectoryPath var archiveURL = URL(fileURLWithPath: currentWorkingPath) archiveURL.appendPathComponent("archive.zip") guard let archive = Archive(url: archiveURL, accessMode: .read) else { return } guard let entry = archive["file.txt"] else { return } var destinationURL = URL(fileURLWithPath: currentWorkingPath) destinationURL.appendPathComponent("out.txt") do { try archive.extract(entry, to: destinationURL) } catch { print("Extracting entry from archive failed with error:\(error)") } Theextractmethod accepts optional parameters that allow you to control compression and memory consumption. You can find detailed information about that parameters in the method’s documentation. Creating Archives To create a newArchive, pass in a non-existing file URL andAccessMode.create. let currentWorkingPath = fileManager.currentDirectoryPath var archiveURL = URL(fileURLWithPath: currentWorkingPath) archiveURL.appendPathComponent("newArchive.zip") guard let archive = Archive(url: archiveURL, accessMode: .create) else { return } Adding and Removing Entries You can add or remove entries to/from archives that have been opened with.createor.updateAccessMode. To add an entry from an existing file, you can pass a relative path and a base URL toaddEntry. The relative path identifies the entry within the ZIP archive. The relative path and the base URL must form an absolute file URL that points to the file you want to add to the archive: let fileManager = FileManager() let currentWorkingPath = fileManager.currentDirectoryPath var archiveURL = URL(fileURLWithPath: currentWorkingPath) archiveURL.appendPathComponent("archive.zip") guard let archive = Archive(url: archiveURL, accessMode: .update) else { return } var fileURL = URL(fileURLWithPath: currentWorkingPath) fileURL.appendPathComponent("file.txt") do { try archive.addEntry(with: fileURL.lastPathComponent, relativeTo: fileURL.deletingLastPathComponent()) } catch { print("Adding entry to ZIP archive failed with error:\(error)") } TheaddEntrymethod accepts several optional parameters that allow you to control compression, memory consumption and file attributes. You can find detailed information about that parameters in the method’s documentation. To remove an entry, you need a reference to an entry within an archive that you can pass toremoveEntry: guard let entry = archive["file.txt"] else { return } do { try archive.remove(entry) } catch { print("Removing entry from ZIP archive failed with error:\(error)") } Closure based Reading and Writing ZIP Foundation also allows you to consume ZIP entry contents without writing them to the file system. Theextractmethod accepts a closure of typeConsumer. This closure is called during extraction until the contents of an entry are exhausted: try archive.extract(entry, consumer: { (data) in print(data.count) }) Thedatapassed into the closure contains chunks of the current entry. You can control the chunk size of the entry by providing the optionalbufferSizeparameter. You can also add entries from an in-memory data source. To do this you have to provide a closure of typeProviderto theaddEntrymethod: try archive.addEntry(with: "fromMemory.txt", type: .file, uncompressedSize: 4, provider: { (position, size) -> Data in guard let data = "abcd".data(using: .utf8) else { throw DataProviderError.invalidEncoding } return data }) The closure is called until enough data has been provided to create an entry ofuncompressedSize. The closure receivespositionandsizearguments so that you can manage the state of your data source.
...全文
309 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

472

社区成员

发帖
与我相关
我的任务
社区描述
其他技术讨论专区
其他 技术论坛(原bbs)
社区管理员
  • 其他技术讨论专区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧