LZMA压缩解压
这里介绍的是如何使用开源的LZMA压缩解压算法库。
里面有头文件、动态库和文档。里面有例子程序,是压缩和解压文件的,我试用过,可以。我这里介绍压缩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)\n", 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; }
最后测试程序证明,可以。