Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a practical way to compress NSData?

I haven't seen any documentation on the topic, but that doesn't mean it doesn't exist.

like image 491
eric.mitchell Avatar asked Dec 08 '11 01:12

eric.mitchell


2 Answers

Swift 3 ready wrapper around libcompression. https://github.com/mw99/DataCompression

Swift libcompression wrapper as an extension for the Data type (ZLIB, LZFSE, LZMA, LZ4, deflate, RFC-1950, RFC-1951)

Interesting to play with in the playground: playground compression rates

like image 98
LimeRed Avatar answered Sep 18 '22 08:09

LimeRed


Starting with iOS 9.0, there is built-in support for a few more compression algorithms. The library is called libcompression and supports LZ4, LZMA, ZLIB and LZFSE.

Here’s a Swift example of using libcompression to decompress LZMA. It’s verbose, but avoids external dependencies and could be hidden in an extension on NSData.

import Compression

let streamPtr = UnsafeMutablePointer<compression_stream>.alloc(1)
var stream = streamPtr.memory
var status: compression_status

status = compression_stream_init(&stream, COMPRESSION_STREAM_DECODE, COMPRESSION_LZMA)
stream.src_ptr = UnsafePointer<UInt8>(compressedData.bytes)
stream.src_size = compressedData.length

let dstBufferSize: size_t = 4096
let dstBufferPtr = UnsafeMutablePointer<UInt8>.alloc(dstBufferSize)
stream.dst_ptr = dstBufferPtr
stream.dst_size = dstBufferSize

let decompressedData = NSMutableData()

repeat {
    status = compression_stream_process(&stream, 0)
    switch status {
    case COMPRESSION_STATUS_OK:
        if stream.dst_size == 0 {
            decompressedData.appendBytes(dstBufferPtr, length: dstBufferSize)
            stream.dst_ptr = dstBufferPtr
            stream.dst_size = dstBufferSize
        }
    case COMPRESSION_STATUS_END:
        if stream.dst_ptr > dstBufferPtr {
            decompressedData.appendBytes(dstBufferPtr, length: stream.dst_ptr - dstBufferPtr)
        }
    default:
        break
    }
}
while status == COMPRESSION_STATUS_OK

compression_stream_destroy(&stream)

if status == COMPRESSION_STATUS_END {
    // Decompression succeeded, do something with decompressedData
}
else {
    // Decompression failed
}
like image 29
jbg Avatar answered Sep 19 '22 08:09

jbg