ios 有没有实用的方法来压缩 NSData?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8425012/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a practical way to compress NSData?
提问by eric.mitchell
I haven't seen any documentation on the topic, but that doesn't mean it doesn't exist.
我还没有看到有关该主题的任何文档,但这并不意味着它不存在。
采纳答案by zaph
Yes, compress the data with zlib.
是的,用 zlib 压缩数据。
@Brad Larson posted on this: see hereand added the code as well.
@Brad Larson 在此发布:请参阅此处并添加代码。
There is a CocoaPodwhich uses Objective-Zipby flyingdolphinstudio.
回答by Adriano Lucas
Following @Zaph & @Brad Larson's posts, below are the 2 methods gzipInflate
and gzipDeflate
that work just fine to compress/decompress NSData
. (code reformatted from cocoadev.com/wiki/NSDataCategory
按照@Zaph 和@Brad Larson 的帖子,下面是两种方法gzipInflate
,gzipDeflate
它们可以很好地压缩/解压缩NSData
。(从cocoadev.com/wiki/NSDataCategory重新格式化的代码
#import "zlib.h"
// don't forget to add libz.1.2.x.dylib into your project
- (NSData *)gzipInflate:(NSData*)data
{
if ([data length] == 0) return data;
unsigned full_length = [data length];
unsigned half_length = [data length] / 2;
NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
BOOL done = NO;
int status;
z_stream strm;
strm.next_in = (Bytef *)[data bytes];
strm.avail_in = [data length];
strm.total_out = 0;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
if (inflateInit2(&strm, (15+32)) != Z_OK) return nil;
while (!done)
{
// Make sure we have enough room and reset the lengths.
if (strm.total_out >= [decompressed length])
[decompressed increaseLengthBy: half_length];
strm.next_out = [decompressed mutableBytes] + strm.total_out;
strm.avail_out = [decompressed length] - strm.total_out;
// Inflate another chunk.
status = inflate (&strm, Z_SYNC_FLUSH);
if (status == Z_STREAM_END) done = YES;
else if (status != Z_OK) break;
}
if (inflateEnd (&strm) != Z_OK) return nil;
// Set real length.
if (done)
{
[decompressed setLength: strm.total_out];
return [NSData dataWithData: decompressed];
}
else return nil;
}
- (NSData *)gzipDeflate:(NSData*)data
{
if ([data length] == 0) return data;
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.total_out = 0;
strm.next_in=(Bytef *)[data bytes];
strm.avail_in = [data length];
// Compresssion Levels:
// Z_NO_COMPRESSION
// Z_BEST_SPEED
// Z_BEST_COMPRESSION
// Z_DEFAULT_COMPRESSION
if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY) != Z_OK) return nil;
NSMutableData *compressed = [NSMutableData dataWithLength:16384]; // 16K chunks for expansion
do {
if (strm.total_out >= [compressed length])
[compressed increaseLengthBy: 16384];
strm.next_out = [compressed mutableBytes] + strm.total_out;
strm.avail_out = [compressed length] - strm.total_out;
deflate(&strm, Z_FINISH);
} while (strm.avail_out == 0);
deflateEnd(&strm);
[compressed setLength: strm.total_out];
return [NSData dataWithData:compressed];
}
From the log:
从日志:
[data length] (orig):989631
[data length] (gz): 102757
[data length] (ungz):989631
回答by jbg
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.
从 iOS 9.0 开始,内置了对更多压缩算法的支持。该库名为 libcompression,支持 LZ4、LZMA、ZLIB 和 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
.
这是使用 libcompression 解压缩 LZMA 的 Swift 示例。它很冗长,但避免了外部依赖,并且可以隐藏在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
}
回答by Blake Watters
I have made a nice Objective-C BZip2 compression interface available as a CocoaPod: https://github.com/blakewatters/BZipCompression
我制作了一个不错的 Objective-C BZip2 压缩接口,可用作 CocoaPod:https: //github.com/blakewatters/BZipCompression
回答by LimeRed
Swift 3 ready wrapper around libcompression. https://github.com/mw99/DataCompression
围绕 libcompression 的 Swift 3 就绪包装器。 https://github.com/mw99/DataCompression
Swift libcompression wrapper as an extension for the Data type (ZLIB, LZFSE, LZMA, LZ4, deflate, RFC-1950, RFC-1951)
Swift libcompression 包装器作为数据类型的扩展(ZLIB、LZFSE、LZMA、LZ4、deflate、RFC-1950、RFC-1951)
Interesting to play with in the playground: playground compression rates
在操场上玩很有趣: 操场压缩率
回答by Ely
In iOS 13 and macOS 10.15 or newer you can use the new compressed
method of NSData
:
在 iOS 13 和 macOS 10.15 或更高版本中,您可以使用以下新compressed
方法NSData
:
let compressedData = try? NSData(data: data).compressed(using: .zlib)
Unfortunately this method hasn't been ported to Swift's native Data
class, but NSData
can be simply casted to Data
by adding as Data
after the above code line.
不幸的是,此方法尚未移植到 Swift 的本机Data
类,但NSData
可以Data
通过as Data
在上述代码行之后添加来简单地转换为。
回答by ZevsVU
Try this: https://github.com/mattt/GodzippaIt was helpful for me.
试试这个:https: //github.com/mattt/Godzippa这对我很有帮助。