iOS LZMA类压缩算法使用
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
提供的代码调用很简单,我根据我的需要,所使用的方法如下:
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.
iOS LZMA类压缩算法使用的更多相关文章
- IOS 公共类-MyDateUtil 日期处理Util
IOS 公共类-MyDateUtil 日期处理Util 此为处理日期的公共类.适用IOS6+ .h文件: #import <Foundation/Foundation.h> //适用 IO ...
- IOS 公共类-MyMBProgressUtil Progress显示
IOS 公共类-MyMBProgressUtil Progress显示 此公共类用于显示提示框,对MBProgress的进一步封装.可以看下面的代码 接口: @interface MyMBProgre ...
- 一位iOS教育类应用开发者是如何赚到60多万美元?
注:伯乐在线12月19日在@程序员的那些事 微博推荐了此文的英文原文,非常感谢@dotSlash 的翻译. 转眼距我写<我如何在iOS教育类应用中赚到20万美元>这篇博文已经一年多了,它 ...
- iOS系类教程之用instruments来检验你的app
比较了好多关于instruments 还是发现老外写的比较牛逼.于是果断翻译过来.有能力的的可以去看英文原版,鼓励大家看原版资料远离二手教程.这里是原文 入门 为了节省大家的时间,提供一个演示的D ...
- iOS方法类:CGAffineTransform的使用大概
CoreGraphics框架中的CGAffineTransform类可用于设定UIView的transform属性,控制视图的缩放.旋转和平移操作: 另称放射变换矩阵,可参照线性代数的矩阵实现方式0. ...
- 006 [翻译] Haneke(一个Swfit iOS缓存类)
Github项目地址:https://github.com/Haneke/HanekeSwift Haneke是一个用swift写成的轻量级iOS类,以简单好用著称(design-decisions- ...
- iOS 在类实现定义中声明成员变量的怪异方式
WebGL 规范(WebGL Specification) 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&quo ...
- iOS 日历类(NSCalendar)
对于时间的操作在开发中很常见,但有时候我们需要获取到一年后的时间,或者一周后的时间.靠通过秒数计算是不行的.那就牵扯到另外一个日历类(NSCalendar).下面先简单看一下 NSDate let d ...
- iOS方法类:CGAffineTransform的使用
CoreGraphics框架中的CGAffineTransform类可用于设定UIView的transform属性,控制视图的缩放.旋转和平移操作: 另称放射变换矩阵,可参照线性代数的矩阵实现方式0. ...
随机推荐
- Java学习笔记-方法引用
方法引用(Method Reference) 上一篇中记录了Lambda表达式,其可以创建匿名方法.当Lambda表达式只是调用一个存在的方法时,可以采用方法引用(JDK8具有的特性).如下: pub ...
- Centos6优化系统服务脚本
#!/bin/bash SysVer=`cat /etc/redhat-release | awk -F'release' '{print $2}' | awk -F'[ .]+' '{print $ ...
- Java 可重入锁
一般意义上的可重入锁就是ReentrantLock http://www.cnblogs.com/hongdada/p/6057370.html 广义上的可重入锁是指: 可重入锁,也叫做递归锁,指的是 ...
- nginx配置Strict Transport Security
一个网站接受一个HTTP的请求,然后跳转到HTTPS,用户可能在开始跳转前,通过没有加密的方式和服务器对话,比如,用户输入http://zt.test.com或者直接zt.test.com.这样存在中 ...
- 【视觉基础知识】Bag of words 在图像中的应用
文章转载自:https://www.cnblogs.com/shihuajie/p/5782515.html BOW (bag of words) 模型简介 Bag of words模型最初被用在文本 ...
- string与位运算
1.String String a="abc"; 会在常量池中开辟一个空间,保存"abc" String b=new String("abc&q ...
- brew 与 nvm
brew 与 nvm 是两个管理软件工具 今天更新了brew结果brew下安装的软件都找不着了.得重新安装,据说brew已经不再更新了.应该是通过github的吧. 结果得重装node与npm,这两 ...
- phalcon: 解决php7/phalcon3.2以上版本,不支持oracle数据库的方法
解决php7/phalcon3.2以上版本,不支持oracle数据库的方法 phalcon3.2(3.0以上)版本不支持oracle的方法. https://github.com/phalcon/in ...
- linux限定用户目录及权限
setfacl -m u:username:rwx dir/file -m:添加或者修改 u[设置用户]:username[用户名]:rwx[设置权限] g[设置组]:groupname[组名]: ...
- poj2823单调队列
这个裸题,滑动窗口求最大最小值,单调队列来两边,一次单调递增q[s]就是最小值,一次单调递减q[s]就是最大值 cin会超时,解除同步也没用... #include<map> #inclu ...