[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7090":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":16,"stars30d":17,"stars90d":15,"forks30d":15,"starsTrendScore":18,"compositeScore":19,"rankGlobal":9,"rankLanguage":9,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":21,"topics":24,"createdAt":9,"pushedAt":9,"updatedAt":27,"readmeContent":28,"aiSummary":29,"trendingCount":15,"starSnapshotCount":15,"syncStatus":30,"lastSyncTime":31,"discoverSource":32},7090,"ZIPFoundation","weichsel\u002FZIPFoundation","weichsel","Effortless ZIP Handling in Swift",null,"Swift",2691,355,24,20,0,3,17,1,62.85,"MIT License",false,"development",true,[25,26],"swift","zip","2026-06-12 04:00:32","\u003Cimg src=\"https:\u002F\u002Fuser-images.githubusercontent.com\u002F1577319\u002F27564151-1d99e3a0-5ad6-11e7-8ab6-417c5b5a3ff2.png\" width=\"489\"\u002F>\n\n[![Swift Package Manager compatible](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FSPM-compatible-brightgreen.svg)](https:\u002F\u002Fgithub.com\u002Fapple\u002Fswift-package-manager)\n[![Carthage compatible](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FCarthage-compatible-4BC51D.svg?style=flat)](https:\u002F\u002Fgithub.com\u002FCarthage\u002FCarthage)\n[![CocoaPods Compatible](https:\u002F\u002Fimg.shields.io\u002Fcocoapods\u002Fv\u002FZIPFoundation.svg)](https:\u002F\u002Fcocoapods.org\u002Fpods\u002FZIPFoundation)\n[![Platform](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FPlatforms-macOS%20|%20iOS%20|%20tvOS%20|%20watchOS%20|%20visionOS%20|%20Linux-lightgrey.svg)](https:\u002F\u002Fgithub.com\u002Fweichsel\u002FZIPFoundation)\n[![Twitter](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Ftwitter-@weichsel-blue.svg?style=flat)](http:\u002F\u002Ftwitter.com\u002Fweichsel)\n\nZIP Foundation is a library to create, read and modify ZIP archive files.\nIt is written in Swift and based on [Apple's libcompression](https:\u002F\u002Fdeveloper.apple.com\u002Fdocumentation\u002Fcompression) for high performance and energy efficiency.\nTo learn more about the performance characteristics of the framework, you can read [this blog post](https:\u002F\u002Fthomas.zoechling.me\u002Fjournal\u002F2017\u002F07\u002FZIPFoundation.html).\n\n- [Features](#features)\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Usage](#usage)\n    - [Zipping Files and Directories](#zipping-files-and-directories)\n    - [Unzipping Archives](#unzipping-archives)\n- [Advanced Usage](#advanced-usage)\n    - [Accessing individual Entries](#accessing-individual-entries)\n    - [Creating Archives](#creating-archives)\n    - [Adding and Removing Entries](#adding-and-removing-entries)\n    - [Closure based Reading and Writing](#closure-based-reading-and-writing)\n    - [In-Memory Archives](#in-memory-archives)    \n    - [Progress Tracking and Cancellation](#progress-tracking-and-cancellation)\n- [Credits](#credits)\n- [License](#license)\n\n## Features\n\n- [x] Modern Swift API\n- [x] High Performance Compression and Decompression\n- [x] Large File Support\n- [x] In-Memory Archives\n- [x] Deterministic Memory Consumption\n- [x] Linux compatibility\n- [x] No 3rd party dependencies (on Apple platforms, zlib on Linux)\n- [x] Comprehensive Unit and Performance Test Coverage\n- [x] Complete Documentation\n\n## Requirements\n\n- iOS 12.0+ \u002F macOS 10.11+ \u002F tvOS 12.0+ \u002F watchOS 2.0+ \u002F visionOS 1.0+\n- Or Linux with zlib development package\n- Xcode 11.0\n- Swift 4.0\n\n## Installation\n\n### Swift Package Manager\nThe Swift Package Manager is a dependency manager integrated with the Swift build system. To learn how to use the Swift Package Manager for your project, please read the [official documentation](https:\u002F\u002Fgithub.com\u002Fapple\u002Fswift-package-manager\u002Fblob\u002Fmaster\u002FDocumentation\u002FUsage.md).  \nTo add ZIP Foundation as a dependency, you have to add it to the `dependencies` of your `Package.swift` file and refer to that dependency in your `target`.\n\n```swift\n\u002F\u002F swift-tools-version:5.0\nimport PackageDescription\nlet package = Package(\n    name: \"\u003CYour Product Name>\",\n    dependencies: [\n\t\t.package(url: \"https:\u002F\u002Fgithub.com\u002Fweichsel\u002FZIPFoundation.git\", .upToNextMajor(from: \"0.9.0\"))\n    ],\n    targets: [\n        .target(\n\t\tname: \"\u003CYour Target Name>\",\n\t\tdependencies: [\"ZIPFoundation\"]),\n    ]\n)\n```\n\nAfter adding the dependency, you can fetch the library with:\n\n```bash\n$ swift package resolve\n```\n\n### Carthage\n\n[Carthage](https:\u002F\u002Fgithub.com\u002FCarthage\u002FCarthage) is a decentralized dependency manager.  \nInstallation instructions can be found in the project's [README file](https:\u002F\u002Fgithub.com\u002FCarthage\u002FCarthage#installing-carthage).\n\nTo integrate ZIPFoundation into your Xcode project using Carthage, you have to add it to your `Cartfile`:\n\n```ogdl\ngithub \"weichsel\u002FZIPFoundation\" ~> 0.9\n```\n\nAfter adding ZIPFoundation to the `Cartfile`, you have to fetch the sources by running:\n\n```bash\ncarthage update --no-build\n```\n\nThe fetched project has to be integrated into your workspace by dragging `ZIPFoundation.xcodeproj` to Xcode's Project Navigator. (See [official Carhage docs](https:\u002F\u002Fgithub.com\u002FCarthage\u002FCarthage#adding-frameworks-to-an-application).)\n\n### CocoaPods\n\nCocoaPods is a dependency manager for Objective-C and Swift.  \nTo learn more about setting up your project for CocoaPods, please refer to the [official documentation](https:\u002F\u002Fcocoapods.org\u002F#install).  \nTo integrate ZIP Foundation into your Xcode project using CocoaPods, you have to add it to your project's `Podfile`:\n\n```ruby\nsource 'https:\u002F\u002Fgithub.com\u002FCocoaPods\u002FSpecs.git'\nplatform :ios, '10.0'\nuse_frameworks!\ntarget '\u003CYour Target Name>' do\n    pod 'ZIPFoundation', '~> 0.9'\nend\n```\n\nAfterwards, run the following command:\n\n```bash\n$ pod install\n```\n\n## Usage\nZIP Foundation provides two high level methods to zip and unzip items. Both are implemented as extension of `FileManager`.  \nThe functionality of those methods is modeled after the behavior of the Archive Utility in macOS.  \n\n### Zipping Files and Directories\nTo zip a single file you simply pass a file URL representing the item you want to zip and a destination URL to `FileManager.zipItem(at sourceURL: URL, to destinationURL: URL)`:\n\n```swift\nlet fileManager = FileManager()\nlet currentWorkingPath = fileManager.currentDirectoryPath\nvar sourceURL = URL(fileURLWithPath: currentWorkingPath)\nsourceURL.appendPathComponent(\"file.txt\")\nvar destinationURL = URL(fileURLWithPath: currentWorkingPath)\ndestinationURL.appendPathComponent(\"archive.zip\")\ndo {\n    try fileManager.zipItem(at: sourceURL, to: destinationURL)\n} catch {\n    print(\"Creation of ZIP archive failed with error:\\(error)\")\n}\n```\n\nBy default, archives are created without any compression. To create compressed ZIP archives, the optional `compressionMethod` parameter has to be set to `.deflate`.  \nThe same method also accepts URLs that represent directory items. In that case, `zipItem` adds the directory content of `sourceURL` to the archive.  \nBy default, a root directory entry named after the `lastPathComponent` of the `sourceURL` is added to the destination archive.  If you don't want to preserve the parent directory of the source in your archive, you can pass `shouldKeepParent: false`.\n\n### Unzipping Archives\nTo unzip existing archives, you can use `FileManager.unzipItem(at sourceURL: URL, to destinationURL: URL)`.  \nThis recursively extracts all entries within the archive to the destination URL:\n\n```swift\nlet fileManager = FileManager()\nlet currentWorkingPath = fileManager.currentDirectoryPath\nvar sourceURL = URL(fileURLWithPath: currentWorkingPath)\nsourceURL.appendPathComponent(\"archive.zip\")\nvar destinationURL = URL(fileURLWithPath: currentWorkingPath)\ndestinationURL.appendPathComponent(\"directory\")\ndo {\n    try fileManager.createDirectory(at: destinationURL, withIntermediateDirectories: true, attributes: nil)\n    try fileManager.unzipItem(at: sourceURL, to: destinationURL)\n} catch {\n    print(\"Extraction of ZIP archive failed with error:\\(error)\")\n}\n```\n\n## Advanced Usage\nZIP 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.\n\n### Accessing individual Entries\nTo gain access to specific ZIP entries, you have to initialize an `Archive` object with a file URL that represents an existing archive. After doing that, entries can be retrieved via their relative path. `Archive` conforms to `Sequence` and therefore supports subscripting:\n\n```swift\nlet fileManager = FileManager()\nlet currentWorkingPath = fileManager.currentDirectoryPath\nvar archiveURL = URL(fileURLWithPath: currentWorkingPath)\narchiveURL.appendPathComponent(\"archive.zip\")\nlet archive = try Archive(url: archiveURL, accessMode: .read)\nguard let entry = archive[\"file.txt\"] else {\n    return\n}\nvar destinationURL = URL(fileURLWithPath: currentWorkingPath)\ndestinationURL.appendPathComponent(\"out.txt\")\ndo {\n    try archive.extract(entry, to: destinationURL)\n} catch {\n    print(\"Extracting entry from archive failed with error:\\(error)\")\n}\n```\n\nThe `extract` method accepts optional parameters that allow you to control compression and memory consumption.  \nYou can find detailed information about that parameters in the method's documentation.\n\n### Creating Archives\nTo create a new `Archive`, pass in a non-existing file URL and `AccessMode.create`.\n\n```swift\nlet fileManager = FileManager()\nlet currentWorkingPath = fileManager.currentDirectoryPath\nvar archiveURL = URL(fileURLWithPath: currentWorkingPath)\narchiveURL.appendPathComponent(\"newArchive.zip\")\nlet archive = try Archive(url: archiveURL, accessMode: .create)\n```\n\n### Adding and Removing Entries\nYou can add or remove entries to\u002Ffrom archives that have been opened with `.create` or `.update` `AccessMode`.\nTo add an entry from an existing file, you can pass a relative path and a base URL to `addEntry`. The relative path identifies the \nentry 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\nthe archive:\n\n```swift\nlet fileManager = FileManager()\nlet currentWorkingPath = fileManager.currentDirectoryPath\nvar archiveURL = URL(fileURLWithPath: currentWorkingPath)\narchiveURL.appendPathComponent(\"archive.zip\")\nlet archive = try Archive(url: archiveURL, accessMode: .update)\nvar fileURL = URL(fileURLWithPath: currentWorkingPath)\nfileURL.appendPathComponent(\"file.txt\")\ndo {\n    try archive.addEntry(with: fileURL.lastPathComponent, relativeTo: fileURL.deletingLastPathComponent())\n} catch {\n    print(\"Adding entry to ZIP archive failed with error:\\(error)\")\n}\n```\n\nAlternatively, the `addEntry(with path: String, fileURL: URL)` method can be used to add files that are _not_ sharing a common base directory. \nThe `fileURL` parameter must contain an absolute file URL that points to a file, symlink or directory on an arbitrary file system location.\n\nThe `addEntry` method accepts several optional parameters that allow you to control compression, memory consumption and file attributes.  \nYou can find detailed information about that parameters in the method's documentation.\n\nTo remove an entry, you need a reference to an entry within an archive that you can pass to `removeEntry`:\n\n```swift\nguard let entry = archive[\"file.txt\"] else {\n    return\n}\ndo {\n    try archive.remove(entry)\n} catch {\n    print(\"Removing entry from ZIP archive failed with error:\\(error)\")\n}\n```\n\n### Closure based Reading and Writing\nZIP Foundation also allows you to consume ZIP entry contents without writing them to the file system. \nThe `extract` method accepts a closure of type `Consumer`. This closure is called during extraction until the contents of an entry are exhausted:  \n\n```swift\ntry archive.extract(entry, consumer: { (data) in\n    print(data.count)\n})\n```   \nThe `data` passed into the closure contains chunks of the current entry. You can control the chunk size of the entry by providing the optional `bufferSize` parameter.\n\nYou can also add entries from an in-memory data source. To do this you have to provide a closure of type `Provider` to the `addEntry` method:\n\n```swift\nlet string = \"abcdefghijkl\"\nguard let data = string.data(using: .utf8) else { return }\ntry? archive.addEntry(with: \"fromMemory.txt\", type: .file, uncompressedSize: Int64(data.count), bufferSize: 4, provider: { (position, size) -> Data in\n    \u002F\u002F This will be called until `data` is exhausted (3x in this case).\n    return data.subdata(in: Data.Index(position)..\u003CInt(position)+size)\n})\n```\nThe closure is called until enough data has been provided to create an entry of `uncompressedSize`. The closure receives `position` and `size` arguments \nso that you can manage the state of your data source.\n\n### In-Memory Archives\nBesides closure based reading and writing of file based archives, ZIP Foundation also provides capabilities to process in-memory archives. \nThis allows creation or extraction of archives that only reside in RAM. One use case for this functionality is dynamic creation of ZIP archives that are later sent to a client - without performing any disk IO.  \n\nTo work with in-memory archives the `init(data: Data, accessMode: AccessMode)` initializer must be used.  \nTo _read_ or _update_ an in-memory archive, the passed-in `data` must contain a representation of a valid ZIP archive.  \nTo _create_ an in-memory archive, the `data` parameter can be omitted:\n\n```swift\nlet string = \"Some string!\"\nlet archive = try Archive(accessMode: .create)\nguard let data = string.data(using: .utf8) else { return }\ntry archive.addEntry(with: \"inMemory.txt\", type: .file, uncompressedSize: Int64(data.count), bufferSize: 4, provider: { (position, size) -> Data in\n    return data.subdata(in: Data.Index(position)..\u003CInt(position)+size)\n})\nlet archiveData = archive.data\n```\n\n### Progress Tracking and Cancellation\nAll `Archive` operations take an optional `progress` parameter. By passing in an instance of [Progress](https:\u002F\u002Fdeveloper.apple.com\u002Fdocumentation\u002Ffoundation\u002Fprogress), you indicate that\nyou want to track the progress of the current ZIP operation. ZIP Foundation automatically configures the `totalUnitCount` of the `progress` object and continuously updates its `completedUnitCount`.  \nTo get notifications about the completed work of the current operation, you can attach a Key-Value Observer to the `fractionCompleted` property of your `progress` object.  \nThe ZIP Foundation `FileManager` extension methods also accept optional `progress` parameters. `zipItem` and `unzipItem` both automatically create a hierarchy of progress objects that reflect the progress of all items contained in a directory or an archive that contains multiple items.  \n\nThe [cancel()](https:\u002F\u002Fdeveloper.apple.com\u002Fdocumentation\u002Ffoundation\u002Fprogress\u002F1413832-cancel) method of `Progress` can be used to terminate an unfinished ZIP operation. In case of cancelation, the current operation throws an `ArchiveError.cancelledOperation` exception. \n\n## Credits\n\nZIP Foundation is written and maintained by [Thomas Zoechling](http:\u002F\u002Fthomas.zoechling.me).  \nTwitter: [@weichsel](https:\u002F\u002Ftwitter.com\u002Fweichsel).\n\n\n## License\n\nZIP Foundation is released under the MIT License.  \nSee [LICENSE](https:\u002F\u002Fgithub.com\u002Fweichsel\u002FZIPFoundation\u002Fblob\u002Fmaster\u002FLICENSE) for details.\n","ZIP Foundation 是一个用于创建、读取和修改 ZIP 文件的 Swift 库。它基于 Apple 的 libcompression 技术，提供高性能压缩和解压功能，并支持大文件处理和内存中归档。该库具备现代 Swift API、确定性内存使用及 Linux 兼容性等特性，且无需第三方依赖（Linux 平台除外）。适用于需要在 iOS、macOS、tvOS、watchOS 或 visionOS 等平台上高效处理 ZIP 文件的应用场景，特别是在对性能和资源管理有较高要求的情况下。",2,"2026-06-11 03:10:29","top_language"]