LZMA压缩解压
這里介紹的是如何使用開源的LZMA壓縮解壓算法庫。
下載地址:http://tukaani.org/xz/
里面有頭文件、動態庫和文檔。里面有例子程序,是壓縮和解壓文件的,我試用過,可以。我這里介紹壓縮buff到另一個buff中,這樣可以實現邊接受來自網絡的數據,邊寫壓縮文件。
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#define LZMA_API_STATIC
#include "lzma.h"
#define LZMA_PRESET_VAL 0
static uint32_t
get_preset()
{
return LZMA_PRESET_VAL | LZMA_PRESET_EXTREME;
}
static bool
get_error(lzma_ret ret)
{
// Return successfully if the initialization went fine.
if (ret == LZMA_OK | LZMA_STREAM_END)
return true;
// Something went wrong. The possible errors are documented in
// lzma/container.h (src/liblzma/api/lzma/container.h in the source
// package or e.g. /usr/include/lzma/container.h depending on the
// install prefix).
const char *msg;
switch (ret) {
case LZMA_MEM_ERROR:
msg = "Memory allocation failed";
break;
case LZMA_OPTIONS_ERROR:
msg = "Specified preset is not supported";
break;
case LZMA_UNSUPPORTED_CHECK:
msg = "Specified integrity check is not supported";
break;
default:
// This is most likely LZMA_PROG_ERROR indicating a bug in
// this program or in liblzma. It is inconvenient to have a
// separate error message for errors that should be impossible
// to occur, but knowing the error code is important for
// debugging. That's why it is good to print the error code
// at least when there is no good error message to show.
msg = "Unknown error, possibly a bug";
break;
}
fprintf(stderr, "Error initializing the encoder: %s (error code %u)
",
msg, ret);
return false;
}
static bool
init_encoder(lzma_stream *strm, uint32_t preset)
{
// Initialize the encoder using a preset. Set the integrity to check
// to CRC64, which is the default in the xz command line tool. If
// the .xz file needs to be decompressed with XZ Embedded, use
// LZMA_CHECK_CRC32 instead.
lzma_ret ret = lzma_easy_encoder(strm, preset, LZMA_CHECK_CRC64);
return get_error(ret);
}
static bool
init_decoder(lzma_stream *strm)
{
// Initialize a .xz decoder. The decoder supports a memory usage limit
// and a set of flags.
//
// The memory usage of the decompressor depends on the settings used
// to compress a .xz file. It can vary from less than a megabyte to
// a few gigabytes, but in practice (at least for now) it rarely
// exceeds 65 MiB because that's how much memory is required to
// decompress files created with "xz -9". Settings requiring more
// memory take extra effort to use and don't (at least for now)
// provide significantly better compression in most cases.
//
// Memory usage limit is useful if it is important that the
// decompressor won't consume gigabytes of memory. The need
// for limiting depends on the application. In this example,
// no memory usage limiting is used. This is done by setting
// the limit to UINT64_MAX.
//
// The .xz format allows concatenating compressed files as is:
//
// echo foo | xz > foobar.xz
// echo bar | xz >> foobar.xz
//
// When decompressing normal standalone .xz files, LZMA_CONCATENATED
// should always be used to support decompression of concatenated
// .xz files. If LZMA_CONCATENATED isn't used, the decoder will stop
// after the first .xz stream. This can be useful when .xz data has
// been embedded inside another file format.
//
// Flags other than LZMA_CONCATENATED are supported too, and can
// be combined with bitwise-or. See lzma/container.h
// (src/liblzma/api/lzma/container.h in the source package or e.g.
// /usr/include/lzma/container.h depending on the install prefix)
// for details.
lzma_ret ret = lzma_stream_decoder(
strm, UINT64_MAX, LZMA_CONCATENATED);
return get_error(ret);
}
static bool
do_lzma_code(lzma_stream *strm, const unsigned char *in_buff,const int in_size, unsigned char *out_buff, int & out_size)
{
lzma_action action = LZMA_FINISH;
uint8_t outbuf[BUFSIZ];
strm->next_out = outbuf;
strm->avail_out = sizeof(outbuf);
strm->next_in = in_buff;
strm->avail_in = in_size;
lzma_ret ret = lzma_code(strm, action);
out_size = sizeof(outbuf) - strm->avail_out;
memcpy(out_buff,outbuf,out_size);
return get_error(ret);
}
void
wang_compress(const unsigned char *in_buff,const int in_size, unsigned char *out_buff, int & out_size)
{
uint32_t preset = get_preset();
lzma_stream strm = LZMA_STREAM_INIT;
bool success = init_encoder(&strm, preset);
if (success)
{
success = do_lzma_code(&strm, in_buff,in_size,out_buff, out_size);
}
lzma_end(&strm);
}
void
wang_decompress(const unsigned char *in_buff,const int in_size, unsigned char *out_buff, int & out_size)
{
lzma_stream strm = LZMA_STREAM_INIT;
bool success = true;
if (!init_decoder(&strm)) {
// Decoder initialization failed. There's no point
// to retry it so we need to exit.
success = false;
}
success &= do_lzma_code(&strm,in_buff,in_size,out_buff,out_size);
lzma_end(&strm);
}
int _tmain(int argc, _TCHAR* argv[])
{
const unsigned char const_string_value[] = "wjfsjfsjfojsofjsojrhghfgehoiheighehgehgieghhgohg osjfi`, sk;f;'l";
std::cout<<const_string_value<<std::endl;
const int const_string_size = strlen((const char*)const_string_value);
std::cout<<const_string_size<<std::endl;
unsigned char buff[1024] = {0};
int size = 0;
wang_compress(const_string_value,const_string_size,buff,size);
std::cout<<size<<std::endl;
unsigned char out_string_value[1024]={0};
int out_string_size = 0;
wang_decompress(buff,size,out_string_value,out_string_size);
assert(out_string_size == const_string_size);
std::cout<<out_string_value<<std::endl;
std::cout<<const_string_size<<std::endl;
std::cin>>out_string_size;
}
最后測試程序證明,可以。
總結
- 上一篇: RNA-Seq分析|RPKM, FPKM
- 下一篇: 极值与最值概念