LZMA(Lempel-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

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

压缩算法

  1. 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);

解压方法

  1. 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);

详细的调用代码如下

  1. - (void)testLZMA {
  2. // Data source file path.
  3. NSString *sourceFilePath = [NSString stringWithFormat:@"%@/source_data.txt", SYSTEM_DOCUMENT_PATH];
  4. // Compressed file path.
  5. NSString *zipFilePath = [NSString stringWithFormat:@"%@/compressed_data.7z", SYSTEM_DOCUMENT_PATH];
  6. NSData *fileData = [NSData dataWithContentsOfFile:sourceFilePath];
  7. DDLogDebug(@"Before compress: %ld bytes", fileData.length);
  8. uint8_t dstBuffer[fileData.length];
  9. memset(dstBuffer, 0, fileData.length);
  10. size_t compressResultLength = compression_encode_buffer(dstBuffer, fileData.length, [fileData bytes], fileData.length, NULL, COMPRESSION_LZMA);
  11. if(compressResultLength > 0) {
  12. NSData *dataAfterCompress = [NSData dataWithBytes:dstBuffer length:compressResultLength];
  13. DDLogDebug(@"Compress successfully. After compress:%ld bytes", dataAfterCompress.length;
  14. // Write compressed data into file.
  15. [dataAfterCompress writeToFile:zipFilePath atomically:YES];
  16. } else {
  17. DDLogError(@"Compress FAILED!!!");
  18. }
  19. }

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

选项2. 集成第三方库LzmaSDKOjbcFramework

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

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

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

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

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

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

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

使用步骤

Step1

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

  1. $ pod install
Step2

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

img
Step3

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

  1. - (void)testLZMA {
  2. NSString *sourceFilePath = [NSString stringWithFormat:@"%@/source_data.txt", SYSTEM_DOCUMENT_PATH];
  3. NSString *zipFilePath = [NSString stringWithFormat:@"%@/compressed_data.7z", SYSTEM_DOCUMENT_PATH];
  4. DDLogDebug(@"\n\n ********** LZMA ********** \nSrc File: %@\n7Zip File:%@\n\n", sourceFilePath, zipFilePath);
  5. // Create writer
  6. LzmaSDKObjCWriter * writer = [[LzmaSDKObjCWriter alloc] initWithFileURL:[NSURL fileURLWithPath:zipFilePath]];
  7. // Add file data's or paths
  8. // [writer addData:[NSData ...] forPath:@"MyArchiveFileName.txt"]; // Add file data
  9. [writer addPath:sourceFilePath forPath:@"."]; // Add file at path
  10. // [writer addPath:@"/Path/SomeDirectory" forPath:@"SomeDirectory"]; // Recursively add directory with all contents
  11. // Setup writer
  12. writer.delegate = self; // Track progress
  13. // writer.passwordGetter = ^NSString*(void) { // Password getter
  14. // return @"1234";
  15. // };
  16. // Optional settings
  17. writer.method = LzmaSDKObjCMethodLZMA; // or LzmaSDKObjCMethodLZMA
  18. writer.solid = YES;
  19. writer.compressionLevel = 7;
  20. writer.encodeContent = YES;
  21. writer.encodeHeader = YES;
  22. writer.compressHeader = YES;
  23. writer.compressHeaderFull = YES;
  24. writer.writeModificationTime = NO;
  25. writer.writeCreationTime = NO;
  26. writer.writeAccessTime = NO;
  27. // Open archive file
  28. NSError * error = nil;
  29. [writer open:&error];
  30. // Write archive within current thread
  31. [writer write];
  32. }

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

ENJOY.

iOS LZMA类压缩算法使用的更多相关文章

  1. IOS 公共类-MyDateUtil 日期处理Util

    IOS 公共类-MyDateUtil 日期处理Util 此为处理日期的公共类.适用IOS6+ .h文件: #import <Foundation/Foundation.h> //适用 IO ...

  2. IOS 公共类-MyMBProgressUtil Progress显示

    IOS 公共类-MyMBProgressUtil Progress显示 此公共类用于显示提示框,对MBProgress的进一步封装.可以看下面的代码 接口: @interface MyMBProgre ...

  3. 一位iOS教育类应用开发者是如何赚到60多万美元?

    注:伯乐在线12月19日在@程序员的那些事 微博推荐了此文的英文原文,非常感谢@dotSlash 的翻译.  转眼距我写<我如何在iOS教育类应用中赚到20万美元>这篇博文已经一年多了,它 ...

  4. iOS系类教程之用instruments来检验你的app

    比较了好多关于instruments 还是发现老外写的比较牛逼.于是果断翻译过来.有能力的的可以去看英文原版,鼓励大家看原版资料远离二手教程.这里是原文   入门 为了节省大家的时间,提供一个演示的D ...

  5. iOS方法类:CGAffineTransform的使用大概

    CoreGraphics框架中的CGAffineTransform类可用于设定UIView的transform属性,控制视图的缩放.旋转和平移操作: 另称放射变换矩阵,可参照线性代数的矩阵实现方式0. ...

  6. 006 [翻译] Haneke(一个Swfit iOS缓存类)

    Github项目地址:https://github.com/Haneke/HanekeSwift Haneke是一个用swift写成的轻量级iOS类,以简单好用著称(design-decisions- ...

  7. iOS 在类实现定义中声明成员变量的怪异方式

    WebGL 规范(WebGL Specification) 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&quo ...

  8. iOS 日历类(NSCalendar)

    对于时间的操作在开发中很常见,但有时候我们需要获取到一年后的时间,或者一周后的时间.靠通过秒数计算是不行的.那就牵扯到另外一个日历类(NSCalendar).下面先简单看一下 NSDate let d ...

  9. iOS方法类:CGAffineTransform的使用

    CoreGraphics框架中的CGAffineTransform类可用于设定UIView的transform属性,控制视图的缩放.旋转和平移操作: 另称放射变换矩阵,可参照线性代数的矩阵实现方式0. ...

随机推荐

  1. think in java

    1.public private protected

  2. 跟着我一起学习大数据——Hadoop

    hadoop配置文件:http://archive.cloudera.com/cdh5/cdh/5/hadoop-2.6.0-cdh5.9.0/ 一:Hadoop简介 总结下起源于Nutch项目,社区 ...

  3. node.js 之 http 架设

    Node.js 安装配置 下载node.js安装mis 打开:cmd cd到node.js安装目录下 输入nodejs --version 显示版本号,证明安装成功 在其根目录下建server.js ...

  4. .Net遍历窗体上控件

    实现遍历窗体上的控件以及找出TextBox控件,代码如下: foreach( Control control in this.Controls ) { if( control is TextBox ) ...

  5. jQuery实际案例②——三层轮播图

    1.如图,这种轮播图需要实现的是,当鼠标移到2上时,第二张图片从右侧过来 2.需要注意的:①很明显这是通过改变z-index与left值来实现的:  ②整体布局需注意,图与数值(1,2,3,4,5)两 ...

  6. Git常用命令和Git团队使用规范指南

    转自:https://wsgzao.github.io/post/git/ 前言 在2005年的某一天,Linux之父Linus Torvalds 发布了他的又一个里程碑作品——Git.它的出现改变了 ...

  7. 数据库原理及应用-SQL数据操纵语言(Data Manipulation Language)和嵌入式SQL&存储过程

    2018-02-19 18:03:54 一.数据操纵语言(Data Manipulation Language) 数据操纵语言是指插入,删除和更新语言. 二.视图(View) 数据库三级模式,两级映射 ...

  8. UVA-11324 The Largest Clique (强连通+DP)

    题目大意:在一张无向图中,最大的节点集使得集合内任意两个节点都能到达对方. 题目分析:找出所有的强连通分量,将每一个分量视作大节点,则原图变成了一张DAG.将每个分量中的节点个数作为节点权值,题目便转 ...

  9. 034——VUE中表单控件处理之使用vue控制radio表单的实例操作

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. 015PHP基础知识——流程控制(三)

    <?php /** *流程控制(三) */ /* 循环结构: while(){ } */ //设置脚本最长执行时间:100秒 //set_time_limit(100); $lantian = ...