iOS LZMA类压缩算法使用

LZMALempel-Ziv-Markov chain-Algorithm的缩写)是2001年以来得到发展的一个数据压缩算法,它用于7-Zip归档工具中的7z格式和 Unix-like 下的 xz 格式。它使用类似于LZ77字典编码机制,在一般的情况下压缩率比bzip2为高,用于压缩的字典文件大小可达4GB。

C++语言写成的LZMA开放源码压缩库使用了区间编码支持的LZ77改进压缩算法以及特殊的用于二进制的预处理程序。LZMA 对数据流、重复序列大小以及重续序列位置单独进行了压缩。LZMA支持几种散列链变体、二叉树以及基数树作为它的字典查找算法基础。

LZMA算法引入

对于数据传输,传输时间和传输质量是主要的两个参考维度。对于传输时间的压缩,数据压缩又是一个很好地可选项。目前正在处理蓝牙BLE(Bluetooth low energy (Bluetooth LE, BLE, marketed as Bluetooth Smart[1]))调试,其中数据传输过程中,发现由于速度限制,传输时间较长,为了缩短传输时间,想利用压缩算法对所要传输的数据进行压缩处理后再进行传输,压缩完成之后再进行传输,以提高传输效率及节省传输时间。经过查阅各种资料,初步使用LZMA压缩算法进行压缩。

之所以选择LZMA算法进行压缩处理,原因有以下几点:

  • 开源
  • iOS & Android平台均支持,可夸平台使用
  • 使用广泛稳定,7zip即采用该算法及衍生算法
  • 压缩效率较高
  • 多线程支持

iOS引入使用LZMA压缩算法方法

选项1. 利用系统默认支持的LZMA压缩算法

Apple提供了一套通用的无损压缩算法,其中就支持LZMA、LZMA2压缩.

The libcompression library provides an API for two styles of data compression:

  • Block compression, where all of the input data is compressed or decompressed by one call to the compression or decompression function.
  • Streaming compression, where the compression or decompression function is called repeatedly to compress or decompress data from a source buffer to a destination buffer. Between calls, processed data is moved out of the destination buffer and new data is loaded into the source buffer.
支持的压缩类型
  • Block Compression
  • Stream Compression
支持的平台如下:
  • iOS 9.0+
  • macOS 10.11+
  • tvOS 9.0+
  • watchOS 2.0+
支持的压缩算法
  • COMPRESSION_LZ4
  • COMPRESSION_ZLIB
  • COMPRESSION_LZMA
  • COMPRESSION_LZFSE

提供的代码调用很简单,我根据我的需要,所使用的方法如下:

压缩算法

size_t compression_encode_buffer(uint8_t *restrict dst_buffer, size_t dst_size, const uint8_t *restrict src_buffer, size_t src_size, void *restrict scratch_buffer, compression_algorithm algorithm);

解压方法

size_t compression_decode_buffer(uint8_t *restrict dst_buffer, size_t dst_size, const uint8_t *restrict src_buffer, size_t src_size, void *restrict scratch_buffer, compression_algorithm algorithm);

详细的调用代码如下

- (void)testLZMA {
    // Data source file path.
    NSString *sourceFilePath = [NSString stringWithFormat:@"%@/source_data.txt", SYSTEM_DOCUMENT_PATH];
    // Compressed file path.
    NSString *zipFilePath = [NSString stringWithFormat:@"%@/compressed_data.7z", SYSTEM_DOCUMENT_PATH];
    
    NSData *fileData = [NSData dataWithContentsOfFile:sourceFilePath];
    DDLogDebug(@"Before compress: %ld bytes", fileData.length);
    
    uint8_t dstBuffer[fileData.length];
    memset(dstBuffer, 0, fileData.length);
    
    size_t compressResultLength = compression_encode_buffer(dstBuffer, fileData.length, [fileData bytes], fileData.length, NULL, COMPRESSION_LZMA);
    if(compressResultLength > 0) {
        NSData *dataAfterCompress = [NSData dataWithBytes:dstBuffer length:compressResultLength];
        DDLogDebug(@"Compress successfully. After compress:%ld bytes", dataAfterCompress.length;
        // Write compressed data into file.
        [dataAfterCompress writeToFile:zipFilePath atomically:YES];
    } else {
        DDLogError(@"Compress FAILED!!!");
    }
}

该方法集成使用起来非常简单,对于基本的压缩需求足够可以满足,且不会对App的大小造成太大影响,不会很大增加,如果没有特殊需求,该方法是首选。

选项2. 集成第三方库LzmaSDKOjbcFramework

这是我最先走的一条路,通过查阅相关资料,引入相关的开源库,自己实现了一个支持LZMA压缩算法的iOS工程用于Build Framework,现已开源到Github上,即LzmaSDKOjbcFramework

虽然最终采用的方案一,但在制作LzmaSDKOjbcFramework过程中,也有一些收获,现分享给大家,愿对大家有些帮助。

最初找到的LZMA的iOS支持库是 LzmaSDKObjC,但是这个库在引入开发工程中过程中,由于使用的cocoaPods, 必须使用use_frameworks! 才可以使用,但是由于podfile中存在其他引入的第三方库,这些库不适用use_frameworks!限制。

此时陷入两难境地,使用use_frameworks!导致其他不支持framework的库不可用,如果不使用,LzmaSDKObjC则会报如下错误:

Codec was not compiled in or stripped by static linking. 
Make sure you are using 'use_frameworks!' and/or dynamic linking ...

而CocoaPods又不支持针对某一第三方库来规定使用use_frameworks!

既然这样,我打算自己创建一个iOS Framework工程开源,供团队内部及所有人方便使用。

使用步骤

Step1

LzmaSDKOjbcFramework工程目录下,由于工程需要Inlineobjc库,所以使用CocoaPods进行安装,命令行执行如下命令:

$ pod install
Step2

打开workspace工程文件,xCode中看到的内容如下:

Step3

Archive工程并导出LzmaSDKObjC.framework文件到所需的工程路径下使用,使用如下:

- (void)testLZMA {
    NSString *sourceFilePath = [NSString stringWithFormat:@"%@/source_data.txt", SYSTEM_DOCUMENT_PATH];
    NSString *zipFilePath = [NSString stringWithFormat:@"%@/compressed_data.7z", SYSTEM_DOCUMENT_PATH];
    DDLogDebug(@"\n\n ********** LZMA ********** \nSrc File: %@\n7Zip File:%@\n\n", sourceFilePath, zipFilePath);
    // Create writer
    LzmaSDKObjCWriter * writer = [[LzmaSDKObjCWriter alloc] initWithFileURL:[NSURL fileURLWithPath:zipFilePath]];
    
    // Add file data's or paths
//    [writer addData:[NSData ...] forPath:@"MyArchiveFileName.txt"]; // Add file data
    [writer addPath:sourceFilePath forPath:@"."]; // Add file at path
//    [writer addPath:@"/Path/SomeDirectory" forPath:@"SomeDirectory"]; // Recursively add directory with all contents
    
    // Setup writer
    writer.delegate = self; // Track progress
//    writer.passwordGetter = ^NSString*(void) { // Password getter
//        return @"1234";
//    };
    
    // Optional settings
    writer.method = LzmaSDKObjCMethodLZMA; // or LzmaSDKObjCMethodLZMA
    writer.solid = YES;
    writer.compressionLevel = 7;
    writer.encodeContent = YES;
    writer.encodeHeader = YES;
    writer.compressHeader = YES;
    writer.compressHeaderFull = YES;
    writer.writeModificationTime = NO;
    writer.writeCreationTime = NO;
    writer.writeAccessTime = NO;
    
    // Open archive file
    NSError * error = nil;
    [writer open:&error];
    
    // Write archive within current thread
    [writer write];
}

该方式的优点是支持的可选项较广,可以广泛的定制各种参数,但缺点是导入库后会导致应用包的体积变大,所以需要根据自身需求来选择。

ENJOY.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,133评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,103评论 4 62
  • 今天是六一,带孩子出去公园玩儿,见到玩具孩子就不停想要,游乐项目也是,玩儿了一个又想玩儿一个。几块钱,几十块的玩具...
    胡瑜珠阅读 208评论 0 0
  • 哈密路记录仪
    艾瑞克666阅读 232评论 0 0
  • 小时候的每年冬天 幺叔总是搬来缝纫机 为我们缝制崭新的棉袄 那兴奋的劲头 只有那年月才有 我总是围在那探究 那神秘...
    冷冬年阅读 401评论 0 1