lzma算法

lzma算法分析

这几天在公司主要在做压缩相关,记录一下所得。
目前业界主流的压缩算法感觉并不多,好用的就Huffman,lz系列,其他的像差分编码,vlq编码,感觉只能做个数据预处理,或者一种小范围的压缩。
lz系列有很多,主要有lz77 lz78 lzma,基本思想是一样的,都是一种字典编码,如,我有一段文本,里面有“abcdefgabcde”,那么后面的abcde并没有必要,可以用前面的替代,所以,其实可存储为“abcdefg65”,6代表offset,5代表length,既用距离当前位置6字节,长度为5的字节串表示当前字节串,由此就减少了三个字节,当然,这里要求0和5也要是u8类型,或者更小。
lz系列核心算法其实很简单,就是这样,但却是业界压缩效果最好的算法,大道至简啊。
lzma就是这么做的,在这里,思考这么几个问题:
1:当压缩算法扫描到中间某段位置时,如何和前面的内容进行快速比较。
2:如何区分当前是压缩的内容,还是未压缩的内容。
首先回答第一个问题,很简单,用哈希,笔者采用了FNV哈希算法,效果挺好的,用c++stl中的hash不知道效果如何,不过其实后来发现,哈希冲突在这里并不严重,一个好的哈希只能带来速度和内存的提升了,没办法提升压缩率的。然后我们如何解决哈希冲突呢,hash冲突这里其实是重点,所表达的就是可能出现了相同字节串。
我们先说这个算法如何工作,

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
lzma算法是一种用于数据压缩的算法,它采用了Lempel-Ziv算法和移动平均算法。在C++中,可以使用LZMA SDK来实现该算法。 首先,需要从LZMA SDK官网下载LZMA SDK,并将其解压缩到本地目录中。然后,在代码中包含头文件"lzma.h",并使用以下代码来进行压缩: ```c++ #include <lzma.h> #include <cstdio> int main() { // 原始数据 char* src = "Hello, world! This is a test for LZMA compression."; // 原始数据长度 size_t src_len = strlen(src) + 1; // 压缩后的数据 char* dst = new char[src_len]; // 压缩后的数据长度 size_t dst_len = src_len; // 压缩级别(1-9,级别越高,压缩率越高,但耗时也越长) int level = 9; // 初始化压缩器 lzma_stream stream = { 0 }; lzma_ret ret = lzma_easy_encoder(&stream, level, LZMA_CHECK_CRC64); // 压缩数据 stream.next_in = (const uint8_t*)src; stream.avail_in = src_len; stream.next_out = (uint8_t*)dst; stream.avail_out = dst_len; ret = lzma_code(&stream, LZMA_FINISH); // 销毁压缩器 lzma_end(&stream); // 输出压缩后的数据 printf("Compressed data: %s\n", dst); // 释放内存 delete[] dst; return 0; } ``` 上述代码中,首先定义了原始数据和压缩后的数据的指针和长度,然后定义了压缩级别。接着,使用`lzma_easy_encoder`函数初始化一个压缩器,并指定压缩级别和校验类型。然后,将原始数据传入压缩器中,进行压缩。最后,使用`lzma_end`函数销毁压缩器,并输出压缩后的数据。 同样地,也可以使用以下代码来进行解压缩: ```c++ #include <lzma.h> #include <cstdio> int main() { // 压缩后的数据 char* src = "...\x5d\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00"; // 压缩后的数据 // 压缩后的数据长度 size_t src_len = 16; // 解压后的数据 char* dst = new char[1024]; // 解压后的数据长度 size_t dst_len = 1024; // 初始化解压器 lzma_stream stream = { 0 }; lzma_ret ret = lzma_stream_decoder(&stream, UINT64_MAX, 0); // 解压数据 stream.next_in = (const uint8_t*)src; stream.avail_in = src_len; stream.next_out = (uint8_t*)dst; stream.avail_out = dst_len; ret = lzma_code(&stream, LZMA_FINISH); // 销毁解压器 lzma_end(&stream); // 输出解压后的数据 printf("Decompressed data: %s\n", dst); // 释放内存 delete[] dst; return 0; } ``` 上述代码中,首先定义了压缩后的数据和解压后的数据的指针和长度。然后,使用`lzma_stream_decoder`函数初始化一个解压器,并指定解压器的内存限制和解压器的特性。接着,将压缩后的数据传入解压器中,进行解压缩。最后,使用`lzma_end`函数销毁解压器,并输出解压后的数据。 需要注意的是,由于LZMA算法的特性,压缩后的数据可能会比原始数据更长,因此在定义压缩后的数据的指针和长度时,需要预留足够的空间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值