1. 程式人生 > >7-zip 下lzma資料解壓縮方式

7-zip 下lzma資料解壓縮方式

那些踩過得神坑:<備註,這個demo的例子有一處是不對的.>

LzmaDecode中的第四個引數:nCompBufLen 應該給第三個引數的實際緩衝區大小.!!!,我操.分析原始碼.和返回值,百度沒有.

本文章介紹的是 LZMA SDK 9.20


7z LZMA 至少需要這三個原始檔

LzmaEnc.c
LzmaDec.c
LzFind.c

和這五個標頭檔案

LzFind.h
LzHash.h
LzmaDec.h
LzmaEnc.h
Types.h

LZMA2 需要在此基礎上附加兩個原始檔

Lzma2Dec.c
Lzma2Enc.c

以及兩個標頭檔案

Lzma2Dec.h
Lzma2Enc.h

LZMA 流介面有 6 個函式,引數含義可顧名思義


CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,

ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);

CLzmaEncHandle 實為 void *

SRes 為狀態返回型別

ISzAlloc、ISeqInStream、ISeqOutStreaem 和 ICompressProgress 為使用者需要提供的四個介面,它們的定義如下


typedef struct
{
void *(*Alloc)(void *p, size_t size);
void (*Free)(void *p, void *address); /* address can be 0 */
} ISzAlloc;

typedef struct
{
SRes (*Read)(void *p, void *buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) < input(*size)) is allowed */
} ISeqInStream;

typedef struct
{
size_t (*Write)(void *p, const void *buf, size_t size);
/* Returns: result - the number of actually written bytes.
(result < size) means error */
} ISeqOutStream;

typedef struct
{
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
/* Returns: result. (result != SZ_OK) means break.
Value (UInt64)(Int64)-1 for size means unknown value. */
} ICompressProgress;

另外注意在實現 ISeqInStream 時,除最後兩次呼叫外,必須每次都提交 *size 位元組的資料,最後兩次中,一次提交所有剩餘資料,另一次提交 0 位元組表示結束,否則 LZMA Encoder 會崩潰。

還有一個 One-Call 介面,把上面的呼叫按照常規邏輯包裝了一下

SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);

LZMA2 的介面與 LZMA 類似,主要不同之處有兩點:

- alloc 和 allocBig 介面被放到了建構函式中
- props 中多了一些引數

http://www.7-zip.org/sdk.html

另外值得一提的是,LZMA 單執行緒在筆記本電池供電時,使用快速模式,對隨機資料的壓縮速度為 4MB/s,壓縮率約為 100%,對全零資料的壓縮速度為 70MB/s,壓縮率約為 0%。 


經過SunOS sun280 5.10驗證的例項(該例項為直接呼叫封裝好的函式):

/* * Simple test program for LZMA SDK's "one call" interface. * */  #include <stdio.h>  #include <string.h>  #include "../../LzmaEnc.h"  #include "../../LzmaDec.h"  #include "../../Alloc.h"  #define COMP_BUFLEN 1000  #define UNCOMP_BUFLEN 5000  char* pTestData;  unsigned char pCompBuf[1000]; /* Compressed data */  unsigned char pUnCompBuf[5000]; /* Unompressed data - at the end its contents */  /* should be equal to contents of pTestData */  static void *SzAlloc(void *p, size_t size) { return MyAlloc(size); }  static void SzFree(void *p, void *address) { MyFree(address); }  int main(int argc, char* argv[])  {      pTestData = "DEADBEEF|askjd9827x34bnzkj#%wioeruxo3b84nxijlhwqdzhwerzu39b87r#_3b9p78bznor83y4fr";      size_t nTestDataLen = strlen(pTestData);      size_t nCompBufLen = COMP_BUFLEN;       size_t nUnCompBufLen = UNCOMP_BUFLEN;       unsigned char pPropsBuf[LZMA_PROPS_SIZE];       size_t nPropsBufLen = LZMA_PROPS_SIZE;       ISzAlloc stAllocator = { SzAlloc, SzFree };       CLzmaEncProps stProps;       ELzmaStatus nStatus;       SRes rc;      int err = 0;       memset(pCompBuf, 0, COMP_BUFLEN);       memset(pUnCompBuf, 0, UNCOMP_BUFLEN); /* Initialize compressor (aka encoder) properties... */       LzmaEncProps_Init(&stProps);       stProps.level = 9;       stProps.dictSize = 1 << 24;       /* ... and compress data. */       printf("dest_len:%d,src_len:%d,prop_len:%d\n",nCompBufLen,nTestDataLen,nPropsBufLen);      rc = LzmaEncode(pCompBuf+LZMA_PROPS_SIZE, &nCompBufLen, (unsigned char*)pTestData, nTestDataLen, &stProps, pPropsBuf, &nPropsBufLen, 0, NULL, &stAllocator, &stAllocator);       if ( rc != SZ_OK )       {        printf("\nLZMA compression failed (rc=%d).\n", rc);        err = 1;        }       else       {      printf("dest_address:%p,dest_len:%d,src_len:%d,dest:%s\n",pCompBuf,nCompBufLen,nTestDataLen,pCompBuf+LZMA_PROPS_SIZE+1);       }      /* Decompress compressed data from previous step */          //nCompBufLen += LZMA_PROPS_SIZE;         nUnCompBufLen = nTestDataLen;      rc = LzmaDecode(pUnCompBuf, &nUnCompBufLen, pCompBuf+LZMA_PROPS_SIZE, &nCompBufLen, pPropsBuf, nPropsBufLen, LZMA_FINISH_ANY, &nStatus, &stAllocator);       if ( rc != SZ_OK )           {            printf("\nLZMA decompression failed (rc=%d, status=%d).\n", rc, nStatus);             err = 1;           }        if ((nUnCompBufLen != nTestDataLen) || memcmp(pTestData, pUnCompBuf, nTestDataLen) )            {            printf("Compression and/or decompression failed!\n");              printf("\tInput data length [nTestDataLen] : %d\n", nTestDataLen);              printf("\tCompressed data length [nCompBufLen] : %d\n", nCompBufLen);              printf("\tUncompressed data length [nUnCompBufLen]: %d\n", nUnCompBufLen);            if ( memcmp(pTestData, pUnCompBuf, nTestDataLen) )                  printf("\tpTestData and pUnCompBuf contain different data!\n");            else              {              printf("\ndest_len:%d\n,dest_data:%s\n,src_src:%s\n",nUnCompBufLen,pUnCompBuf,pTestData);              }              err = 1;             }            printf("\ndest_len:%d\n,dest_data:%s\n,src_src:%s\n",nUnCompBufLen,pUnCompBuf,pTestData);         if ( !err )          printf("\nOK!\n");           return 0; }
詳情請瀏覽sdk說明文件或者LZMA官方論壇(http://sourceforge.net/projects/sevenzip/forums/forum/45797/topic/4698263)

備註:
         

        整整三天才搞出來,今天終於可以好好睡覺了。學程式設計的同學啊,要加強英語的學習啊。

原文轉載自:http://blog.163.com/[email protected]/blog/static/1018865812012499356225/

相關推薦

7-zip lzma資料壓縮方式

那些踩過得神坑:<備註,這個demo的例子有一處是不對的.> LzmaDecode中的第四個引數:nCompBufLen 應該給第三個引數的實際緩衝區大小.!!!,我操.分析原始碼.和返回值,百度沒有. 本文章介紹的是 LZMA SDK 9.20 7z

CentOS 安裝7-Zip 以及常用的壓命令

在SHH或者終端下輸入:yum –y install p7zip(如果提示找不到資源,則要自己下載編譯安裝,命令如:) wget http://nchc.dl.sourceforge.net/sourceforge/p7zip/p7zip_4.65_src

tar、zip、gzip等壓縮命令

解壓縮tar命令:壓縮:tar cf 壓縮後的文件名.tar.gz 壓縮前的文件或者目錄解壓:tar xf 壓縮後的文件名.tar.gz查看壓縮裏的內容:tar tf 壓縮後的文件名.tar.gz zip命令:壓縮目錄:zip –r /opt/etc.zip /etc 解壓:unzip /opt/etc.

LearnPython - Zip格式檔案的壓縮

1 import zipfile 2 import os 3 4 5 def unzip(zip_name, target_dir): 6 files = zipfile.ZipFile(zip_name) 7 for zip_file in files.namelis

對稱矩陣壓縮和三種壓縮方式

#include<iostream> #include<stdio.h> #include<math.h> #define SIZE 5 using namespace std; int* Compress(int *m) { int*n = (

ubuntu建立資料夾快捷方式

title: ubuntu下建立資料夾快捷方式 toc: false date: 2018-09-01 17:22:28 categories: methods tags: ubuntu 快捷方式 sudo ln -sT [srcDir] [dstDir/name]

linux中 gzip bizp2 xz zip怎麼用,壓縮

linux 中常用的壓縮指令           壓縮  gzip bzip2 xz , 解壓gunzip  unxz bunzip2 解壓對應的壓縮包 *.tar.gz  *.tar.xz  *.tar.bz2(由於 compress 效率底下,已經丟棄不用啦) 選項

Windows安裝MySQL壓縮

1.去官網下載.zip格式的MySQL Server的壓縮包,根據需要選擇x86或x64版。 2.解壓縮至你想要的位置。 3.在解壓檔案目錄下新建空白檔案,重新命名為my.ini。並新增以下內容(路徑要根據自己的情況修改呀)。沒有data目錄不要緊,下一步處理這個事情

Java壓縮zip檔案工具類(支援zip資料多級目錄結構)

文章目錄 Java解壓縮zip檔案工具類(支援zip資料夾下多級目錄結構) 1. 前言 2. 正文 2.1 解壓縮後文件目錄結構展示 2.2 注意事項 2.3 異常

Linux壓縮zip,壓縮unzip命令詳及實例

cnblogs http .com 服務器 file html htm unzip inux http://www.cnblogs.com/zdz8207/p/3765604.html Linux下的壓縮解壓縮命令詳解及實例 實例:壓縮服務器上當前目錄的內容為xx

WIN 10Mysql 5.7.21壓縮(免安裝版)配置

控制 roo 5.7 ogr 很多 mysql 5.7 mysql數據庫 l數據庫 服務 網上看了N多大神的東西東抄抄西抄抄,老是就不對,因為很多資料不是針對5.7這個版本的內容。 首先解壓文件,比如我解壓到D:\Program Files\mysql-5.7.21-wi

zip壓縮/壓縮帶空資料夾的檔案

zip壓縮/解壓縮帶空資料夾的檔案 2011年07月21日 20:04:54 flex_work 閱讀數:7152 標籤: filestringbytebuffernullinclude 更多 個人分類: Flex And Java

CentOS5/6/7系統搭建安裝Amabari大資料叢集時出現SSLError: Failed to connect. Please check openssl library versions.錯誤的解決辦法(圖文詳

        不多說,直接上乾貨!         ========================== Creating target directory... ======================

window 10 壓縮版MySQL5.7.24的安裝

安裝步驟: 1.下載mysql-5.6.40-winx64.zip https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.24-winx64.zip 2.解壓mysql5.7.24 3.配置mysql的環境變數 在path中新增:;D:\mysql

WINDOWSMySQL 5.7+ 壓縮版安裝配置方法

1.去官網下載.zip格式的MySQL Server的壓縮包,根據需要選擇x86或x64版。注意:下載是需要註冊賬戶並登入的。 2.解壓縮至你想要的位置。 3.複製解壓目錄下my-dafault.ini至bin目錄下,重新命名為my.ini。並新增以下內容(路徑要根據自己的情況修改呀)。沒有data目錄不

Linux 壓縮壓縮 zip、binzip2、tar、zip命令的使用

我們經常需要對檔案壓縮或打包實現統一管理,下面就讓我們來看看gzip、bzip2、tar、zip這些命令的使用 (1)    gzip 格式:gzip [選項] [檔案] 示例: ---在testzip目錄下有以下檔案 --

Linux壓縮zip,tar命令詳及例項

Linux下的壓縮解壓縮命令詳解及例項 例項:壓縮伺服器上當前目錄的內容為xxx.zip檔案 zip -r xxx.zip ./* 解壓zip檔案到當前目錄 unzip filename.zip ============================ 另:有些伺服器

Linux壓命令大全 壓縮 tar bz2 zip tar.gz gz

大致總結了一下linux下各種格式的壓縮包的壓縮、解壓方法。但是部分方法我沒有用到,也就不全,希望大家幫我補充,我將隨時修改完善,謝謝!整理:會游泳的魚 來自:www.LinuxByte.net 最後更新時間:2005-2-20 .tar 解包:tar xvf FileName.tar 打包:tar cvf

Linuxtar.gz、tar、bz2、zip等格式壓縮壓縮命令小結

Linux下最常用的打包程式就是tar了,使用tar程式打出來的包我們常稱為tar包,tar包檔案的命令通常都是以.tar結尾的。生成tar包後,就可以用其它的程式來進行壓縮了,所以首先就來講講tar命令的基本用法:   tar命令的選項有很多(用man tar可以檢視到),但常用的就那麼幾個選項,下面 來舉

linuxtar.gz、tar、bz2、zip壓縮壓縮命令小結

Linux下最常用的打包程式就是tar了,使用tar程式打出來的包我們常稱為tar包,tar包檔案的命令通常都是以.tar結尾的。生成tar包後,就可以用其它的程式來進 行壓縮了,所以首先就來講講tar命令的基本用法:   tar命令的選項有很多(用man tar可以檢視到