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閱讀 230,106評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,728評論 25 708
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,172評論 4 61
  • 今天是六一,帶孩子出去公園玩兒,見到玩具孩子就不停想要,游樂項目也是,玩兒了一個又想玩兒一個。幾塊錢,幾十塊的玩具...
    胡瑜珠閱讀 214評論 0 0
  • 哈密路記錄儀
    艾瑞克666閱讀 306評論 0 0
  • 小時候的每年冬天 幺叔總是搬來縫紉機 為我們縫制嶄新的棉襖 那興奮的勁頭 只有那年月才有 我總是圍在那探究 那神秘...
    冷冬年閱讀 415評論 0 1