Giter VIP home page Giter VIP logo

swiftzip's Introduction

Overview

macOS iOS Linux

SwiftZip is a Swift wrapper for libzip providing an API to read, create and modify zip archives. Files can be added from data buffers, files, or compressed data copied directly from other zip archives. Changes made without closing the archive can be reverted.

Note: SwiftZip is currently under development and API may change slightly as the project evolves.

Getting Started

Quick Instructions

Opening and inspecting an archive:

do {
    // Open an archive for reading
    let archive = try ZipArchive(url: archiveUrl)

    // Enumerate entries in the archive
    for entry in archive.entries {
        // Get basic entry information
        let name = try entry.getName()
        let size = try entry.stat().size
        print("\(name) -> \(size as Any)")

        // Read entry contents into a `Data` instance
        let data = try entry.data()
        print(data)
    }
} catch {
    // Handle possible errors
    print("\(error)")
}

Creating an archive:

do {
    // Open an archive for writing, overwriting any existing file
    let archive = try ZipMutableArchive(url: archiveUrl, flags: [.create, .truncate])

    // Load the test data
    let data = try Data(contentsOf: dataUrl)

    // Create a data source and add it to the archive
    let source = try ZipSource(data: data)
    try archive.addFile(name: "filename.dat", source: source)

    // Commit changes and close the archive
    // Alternatively call `discard` to rollback any changes
    try archive.close()
} catch {
    // Handle possible errors
    print("\(error)")
}

Getting More Help

Auto-generated documentation based on libzip manual is available at https://swiftzip.github.io/.

SwiftZip is designed to be a thin wrapper aroung libzip. Please refer to the original libzip documentation to get more details on the underlying implementation: https://libzip.org/documentation/.

Current libzip API mapping and coverage is available at API.md

Installation

Swift Package Manager

To depend on the SwiftZip package, you need to declare your dependency in your Package.swift file:

dependencies: [
    .package(url: "https://github.com/SwiftZip/SwiftZip.git", .branch("master")),
    // ...
]

and add "SwiftZip" to your application/library target dependencies, e.g. like this:

.target(name: "BestExampleApp", dependencies: [
    "SwiftZip",
    // ...
])

Using SwiftZip on Linux

SwiftZip requires BZip2 and OpenSSL development packages to be installed when building on Linux. You can install the required dependencies using apt on Ubuntu:

apt-get install libbz2-dev
apt-get install libssl-dev

SwiftZip Project

SwiftZip in currently under development. Please open an issue or submit a pull request in case you find any issues or have any improvement ideas.

Project Goals

  • the primary goal of the SwiftZip project is to provide first-class Swift bindings for libzip on all supported platforms
  • the initial target is the iOS platform without any external dependencies, macOS and Linux targets will be added later

Design Considerations

  • libzip must be included "as is" without any modifications to allow easy drop-in updates
  • the library should be entirely opaque providing a native Swift interface for all libzip functionality
  • the binding layer should propagate all underlying errors so client code can properly handle them

Project Structure

  • all libzip-related files are located under the Sources/zip directory and exposed as zip package
  • Sources/zip/libzip is a submodule referencing relevant libzip source code
  • Sources/zip/libzip-patches folder contains patches to be applied to the libzip header files, so they are compatible with the Swift package manager
  • Sources/zip/include contains public headers for the libzip as required by the Swift package manager
  • Sources/zip/include-private contains patched private headers to build libzip
  • Swift wrappers are located under the Sources/SwiftZip directory and exposed as SwiftZip package

Updating libzip

The SwiftZip wrapper is designed to make libzip updates as easy as possible. To update the underlying library, use the ./Tools/libzip-update.sh script to pull the latest version in the Sources/zip/libzip submodule and update public headers.

TODO/Roadmap:

  • provide an initial set of wrappers for archive operations
  • adapt libzip docs and convert them to code comments
  • provide Swift protocol-based wrapper for custom sources API
  • add Linux build support
  • cover core functionality with tests based on libzip test suite

License

swiftzip's People

Contributors

victor-pavlychko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

swiftzip's Issues

SwiftZip failing to build for visionOS

Looks like there's a failure when attempting to build SwiftZip for the new Apple visionOS:

In file included from /Users/[...]/SwiftZip/Sources/zip/libzip/lib/zip_unchange_archive.c:37:
/Users/[...]/SwiftZip/Sources/zip/libzip/lib/zipint.h:37:10: fatal error: 'config.h' file not found
#include "config.h"
         ^~~~~~~~~~
1 error generated.

Is this just a matter of re-configuring libzip?

Assertion failed: Failed to read N bytes. Got M instead.: file SwiftZip/ZipEntry+Utils.swift, line 37

Hello,

I have a UICollectionView which has various UICollectionViewCells (usually around 200 cells approx.).

Every cell displays an image that is inside the Zip File.

In order to load the image that's inside the Zip file, I developed this code:

func getPage(name: String, at index: Int, compression: CGFloat) -> UIImage {
        if let cachedImage = ImageCache.shared.object(forKey: "\(name)-\(index)-thumbnail" as NSString) {
            return cachedImage
        } else {
            do {
                let data = try entries[index].data() // <- The error is here
                if let image = UIImage(data: data)?.resized(withPercentage: compression) {
                    ImageCache.shared.setObject(image, forKey: "\(name)-\(index)-thumbnail" as NSString)
                    return image
                } else {
                    return UIImage()
                }
            } catch let error {
                print("Error getting page: \(error)")
                return UIImage()
            }
        }
    }
`func cellForPage(at indexPath: IndexPath) -> UICollectionViewCell {
    let cell = mainCV.dequeueReusableCell(withReuseIdentifier: kSmallPageCVC, for: indexPath) as! SmallPageCVC
    DispatchQueue.global(qos: .userInteractive).async {
        let image = self.getPage(name: self.name, at: indexPath.row, compression: 0.35)
        cell.configureCell(image:image)
    }
    return cell
}`

However, sometimes the SDK shows this error:

Error getting page: LibZip error: Zlib error: data error

And if I slide the UICollectionView very fast, it shows this fatal error:

Assertion failed: Failed to read 864937 bytes. Got 564606 instead.: file SwiftZip/ZipEntry+Utils.swift, line 37

Could anyone, please, give me any hint on why is this happening?

Thank you very much.

Best regards

Expose libzip's built-in encoding guessing

Hi,

First of all, great project. I think a solid Swift wrapper around libzip is just what the Swift community needs.

I'm having some problems with 0.0.3. I see you replaced libzip's built-in encoding guessing with a Foundation based one. I'm sure there are good reasons, but for my purposes this is much too slow. It causes a ~600% slowdown of my code in comparison to 0.0.2, to the point where ~85% of the total time searching for and extracting a file is spent on encoding guessing (very large zip file).

I think it would be a good idea to expose the built-in strategy from Swift, preferably by default. Maybe decodingStrategy could be an enum with an additional case for Foundation based guessing.

entry.data() just returns no data just "627 bytes"

my code:

for entry in archive.entries(version: .current) {
        // Get basic entry information
        let name = try entry.getName()
        let size = try entry.stat().size
        print("\(name) -> \(size as Any)")

        // Read entry contents into a `Data` instance
        let data = try entry.data()
        print(data)
    }

results:

➜  MyAppSwift swift run MyAppSwift
[2/2] Merging module MyAppSwift
document.json -> Optional(627)
627 bytes
pages/DD2372FD-EEFA-4F85-BDBD-D24EF3C1E124.json -> Optional(22888)
22888 bytes

this should return the contents of the file not the file size or am I doing something wrong here?

How to mark one file as not to be compressed?

I am trying to programmatically make an ePub file. To do this I need to have an uncompressed "mimetype" file contained in the zip. Can I use SwiftZip and mark one file as not to be compressed or simply create the zip file with no compression for any files? I can't see anywhere in the documentation for how this would be done.

Assertion failed: Failed to read N bytes. Got M instead.: file SwiftZip/ZipEntry+Utils.swift, line 37

Hello,

I have a UICollectionView which has various UICollectionViewCells (usually around 200 cells approx.).

Every cell displays an image that is inside the Zip File.

In order to load the image that's inside the Zip file, I developed this code:

`func getPage(name: String, at index: Int, compression: CGFloat) -> UIImage {
if let cachedImage = ImageCache.shared.object(forKey: "(name)-(index)-thumbnail" as NSString) {
return cachedImage
} else {
do {
let data = try entries[index].data()
if let image = UIImage(data: data)?.resized(withPercentage: compression) {
ImageCache.shared.setObject(image, forKey: "(name)-(index)-thumbnail" as NSString)
return image
} else {
return UIImage()
}
} catch let error {
print("Error getting page: (error)")
return UIImage()
}
}
}

func cellForPage(at indexPath: IndexPath) -> UICollectionViewCell {
    let cell = mainCV.dequeueReusableCell(withReuseIdentifier: kSmallPageCVC, for: indexPath) as! SmallPageCVC
    DispatchQueue.global(qos: .userInteractive).async {
        let image = self.getPage(name: self.name, at: indexPath.row, compression: 0.35)
        cell.configureCell(image:image)
    }
    return cell
}`

However, sometimes the SDK shows this error:

Error getting page: LibZip error: Zlib error: data error

And if I slide the UICollectionView very fast, it shows this fatal error:

Assertion failed: Failed to read 864937 bytes. Got 564606 instead.: file SwiftZip/ZipEntry+Utils.swift, line 37

Could anyone, please, give me any hint on why is this happening?

Thank you very much.

Best regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.