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. ...
随机推荐
- hadoop随手笔记
1.Hadoop Streaming 是为了方便不太熟悉java用户编写MR程序的工具.用户可以将任何可执行文件(C++)或者脚本(python,ruby)作为Mapper/Reducer, 提高了效 ...
- MR案例:定制InputFormat
数据输入格式 InputFormat类用于描述MR作业的输入规范,主要功能:输入规范检查(比如输入文件目录的检查).对数据文件进行输入切分和从输入分块中将数据记录逐一读取出来.并转化为Map的输入键值 ...
- 如何为openwrt中的某个模块生成PKG_MIRROR_HASH
答:介绍两种方法,第一种自动生成(当然使用自动的啦),第二种手动生成 第一种方法: 1.在软件包的Makefile中让此项写成这样PKG_MIRROR_HASH:=skip (如果不加上skip,那 ...
- Can't connect to any repository: xxxxxx Error writing request body to server
今天在git提交代码时一直报如下错误: Can't connect to any repository: https://gitee.com/xxxxxx(https://gitee.com/xxxx ...
- ANR异常
ANR异常 一.简介 解决方法:别在主线程中写非常耗时的操作 二.代码实例 点击之后,不停点击,乱点 出现anr异常 代码 /anr/src/anr/MainActivity.java package ...
- Number.MIN_VALUE常量说明
Number.MIN_VALUE常量说明 Number.MIN_VALUE表示的最小值为5e-324 MIN_VALUE代表的并不是负最小,而是最接近0的一个数 负最小值可以使用-Number.MAX ...
- 设计模式--门面模式C++实现
门面模式C++实现 1定义facade 要求一个子系统的外部接口与其内部的通信必须通过一个统一的接口进行.门面模式提供一个高层次的接口,使得子系统更容易视同 注:门面模式注重统一对象,也就是提供一个访 ...
- UVA-10765 Doves and bombs (双连通分量)
题目大意:给一个n个点的无向连通图,找出删除某个点后的连通块个数. 题目分析:统计一下每个节点属于几个双连通分量,若是割点,得到的便是答案,否则答案为1. 代码如下: # include<ios ...
- OC与JS的交互详解
事情的起因还是因为项目需求驱动.折腾了两天,由于之前没有UIWebView与JS交互的经历,并且觉得这次在功能上有一定的创造性,特此留下一点文字,方便日后回顾. 我要实现这样一个需求:按照本地的CSS ...
- GitHub:Git的使用
1.下载安装后设置姓名和邮箱地址 $ git config --global user.name "yourGithubName" $ git config --global us ...