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. ...
随机推荐
- # fabirc 配置多组服务器 密码与密钥一起使用 key_filename的设置
环境说明 myv myv2 是配置在/etc/hosts 的两台 虚拟机 虚拟机ip. 参考英文文档 官方文档的例子不是给的很详细.. http://docs.fabfile.org/en/1.13/ ...
- Mybatis实现批量删除
知识点:当传入参数为数组时,XX.xml文件中,标签为collection属性 参考博客:https://blog.csdn.net/javaee_sunny/article/details/5251 ...
- 从0开始 图论学习 邻接表 STL vector
邻接表表示 用vector实现 writer:pprp 代码如下: #include <bits/stdc++.h> using namespace std; const int maxn ...
- Kubernetes 部署失败的 10 个最普遍原因
[原文].后面我们可能还会看到一个 OOMKilled 错误. 我们的应用正在挂掉?为什么? 首先我们查看应用日志.假定你发送应用日志到 stdout(事实上你也应该这么做),你可以使用 kubect ...
- @configurationProperties的写法
- JavaScript高级程序设计-读书笔记(2)
第6章 面向对象的程序设计 创建对象 1.最简单方式创建Object的实例,如 var person = new Object(); person.name = “Greg”; person.age ...
- 关于javascript以及jquery如何打开文件
其实很简单, <input type="file" id="file" mce_style="display:none"> 这个 ...
- struts2中<s:checkboxlist/>的用法详解
Html代码 选择角色<br> <s:checkboxlist list="#request.roleuserList" listKey="roleId ...
- js 图片查看器
将以前用angular 写的 自定义指令 封装成 插件,无需引用jquery.angular. 下载下来即可查看效果. github网址: https://github.com/wzhGitH/img ...
- Codeforces Round #428 (Div. 2)E. Mother of Dragons
http://codeforces.com/contest/839/problem/E 最大团裸题= =,用Bron–Kerbosch算法,复杂度大多博客上没有,维基上查了查大约是O(3n/3) 最大 ...