iOS LZMA類壓縮算法使用

LZMALempel-Ziv-Markov chain-Algorithm的縮寫)是2001年以來得到發(fā)展的一個數(shù)據(jù)壓縮算法,它用于7-Zip歸檔工具中的7z格式和 Unix-like 下的 xz 格式。它使用類似于LZ77字典編碼機制,在一般的情況下壓縮率比bzip2為高,用于壓縮的字典文件大小可達4GB。

C++語言寫成的LZMA開放源碼壓縮庫使用了區(qū)間編碼支持的LZ77改進壓縮算法以及特殊的用于二進制的預處理程序。LZMA 對數(shù)據(jù)流、重復序列大小以及重續(xù)序列位置單獨進行了壓縮。LZMA支持幾種散列鏈變體、二叉樹以及基數(shù)樹作為它的字典查找算法基礎。

LZMA算法引入

對于數(shù)據(jù)傳輸,傳輸時間和傳輸質量是主要的兩個參考維度。對于傳輸時間的壓縮,數(shù)據(jù)壓縮又是一個很好地可選項。目前正在處理藍牙BLE(Bluetooth low energy (Bluetooth LE, BLE, marketed as Bluetooth Smart[1]))調試,其中數(shù)據(jù)傳輸過程中,發(fā)現(xiàn)由于速度限制,傳輸時間較長,為了縮短傳輸時間,想利用壓縮算法對所要傳輸?shù)臄?shù)據(jù)進行壓縮處理后再進行傳輸,壓縮完成之后再進行傳輸,以提高傳輸效率及節(jié)省傳輸時間。經(jīng)過查閱各種資料,初步使用LZMA壓縮算法進行壓縮。

之所以選擇LZMA算法進行壓縮處理,原因有以下幾點:

  • 開源
  • iOS & Android平臺均支持,可夸平臺使用
  • 使用廣泛穩(wěn)定,7zip即采用該算法及衍生算法
  • 壓縮效率較高
  • 多線程支持

iOS引入使用LZMA壓縮算法方法

選項1. 利用系統(tǒng)默認支持的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

提供的代碼調用很簡單,我根據(jù)我的需要,所使用的方法如下:

壓縮算法

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

這是我最先走的一條路,通過查閱相關資料,引入相關的開源庫,自己實現(xiàn)了一個支持LZMA壓縮算法的iOS工程用于Build Framework,現(xiàn)已開源到Github上,即LzmaSDKOjbcFramework

雖然最終采用的方案一,但在制作LzmaSDKOjbcFramework過程中,也有一些收獲,現(xiàn)分享給大家,愿對大家有些幫助。

最初找到的LZMA的iOS支持庫是 LzmaSDKObjC,但是這個庫在引入開發(fā)工程中過程中,由于使用的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又不支持針對某一第三方庫來規(guī)定使用use_frameworks!

既然這樣,我打算自己創(chuàng)建一個iOS Framework工程開源,供團隊內部及所有人方便使用。

使用步驟

Step1

LzmaSDKOjbcFramework工程目錄下,由于工程需要Inlineobjc庫,所以使用CocoaPods進行安裝,命令行執(zhí)行如下命令:

$ 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];
}

該方式的優(yōu)點是支持的可選項較廣,可以廣泛的定制各種參數(shù),但缺點是導入庫后會導致應用包的體積變大,所以需要根據(jù)自身需求來選擇。

ENJOY.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

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