【问题标题】:LzmaLib: compress / decompress buffer in CLzmaLib:在 C 中压缩/解压缩缓冲区
【发布时间】:2016-11-22 02:43:08
【问题描述】:

我正在尝试将LzmaLibLzmaCompress()LzmaDecompress() 与缓冲区一起使用,调整here 提供的示例。

我正在使用 ~3MB 缓冲区进行测试,压缩功能似乎工作正常(产生 ~1.2MB 压缩缓冲区),但是当我尝试解压缩时,它只提取 ~300 字节并返回 SZ_ERROR_DATA

提取的几个字节是对的,但我不知道为什么它停在那里。

我的代码:

#include <stdio.h>
#include <stdlib.h>

#include "LzmaLib.h"

void compress(
    unsigned char **outBuf, size_t *dstLen,
    unsigned char *inBuf, size_t srcLen)
{
    unsigned propsSize = LZMA_PROPS_SIZE;
    *dstLen = srcLen + srcLen / 3 + 128;

    *outBuf = (unsigned char*)malloc(propsSize + *dstLen);

    int res = LzmaCompress(
        (unsigned char*)(*outBuf + LZMA_PROPS_SIZE), dstLen,
        inBuf, srcLen,
        *outBuf, &propsSize,
        -1, 0, -1, -1, -1, -1, -1);

    assert(res == SZ_OK);

    *dstLen = *dstLen + LZMA_PROPS_SIZE;
}

void uncompress(
    unsigned char **outBuf, size_t *dstLen,
    unsigned char *inBuf,  size_t srcLen
) {
    *dstLen = 5000000;
    *outBuf = (unsigned char*)malloc(*dstLen);

    srcLen = srcLen - LZMA_PROPS_SIZE;
    int res = LzmaUncompress(
        *outBuf, dstLen,
        (unsigned char*)(inBuf + LZMA_PROPS_SIZE), &srcLen,
        inBuf, LZMA_PROPS_SIZE);

    assert(res == SZ_OK);
}

void do_compress() {
    FILE* file = fopen("Module.dll", "r");
    size_t size, decSize;
    unsigned char *data, *dec = NULL;

    fseek(file, 0L, SEEK_END);
    size = ftell(file);
    fseek(file, 0L, SEEK_SET);

    data = (unsigned char*)malloc(size);
    fread(data, 1, size, file);
    fclose(file);

    compress((unsigned char**)&dec, &decSize, data, size);

    file = fopen("Module.lzma", "w");
    fwrite(dec, 1, decSize, file);
    fclose(file);
}

void do_uncompress() {
    FILE* file = fopen("Module.lzma", "r");
    size_t size, decSize;
    unsigned char *data, *dec = NULL;

    fseek(file, 0L, SEEK_END);
    size = ftell(file);
    fseek(file, 0L, SEEK_SET);

    data = (unsigned char*)malloc(size);
    fread(data, 1, size, file);
    fclose(file);

    uncompress((unsigned char**)&dec, &decSize, data, size);

    file = fopen("Module_DEC.dll", "w");
    fwrite(dec, 1, decSize, file);
    fclose(file);
}

int main()
{
    do_compress();
    do_uncompress();

    return 0;
}

如果此代码不是使用 LzmaLib 压缩缓冲区的更好方法,我很乐意接受建议。

【问题讨论】:

  • 我通过dstLen 并且问题仍然存在。只解压了几个字节,返回错误 1 ​​(SZ_ERROR_DATA)。

标签: c compression 7zip lzma


【解决方案1】:

我敢打赌,问题在于您如何读取/写入文件。您需要以二进制模式打开它们以防止在读/写操作期间进行任何替换。

更改以下所有实例:

  • fopen(xxx, "r") -> fopen(xxx, "rb")
  • fopen(xxx, "w") -> fopen(xxx, "wb")

【讨论】:

  • 伙计,我不能说出我现在在想的话。那是确切的问题。非常感谢。
  • 小错误最难发现:)
【解决方案2】:

我没有专门检查 LzmaCompress,但大多数其他压缩库(如 libz)处理该函数类似于标准的读/写或 fread/fwrite 函数,即允许您连续调用函数以压缩更多一个流中的更多数据。因此,在某些时候,您将不得不说“我已经完成了,请刷新到目前为止未写的所有内容”。可能,你忘记了那部分。如果没有,Minimal, Complete, and Verifiable example 会很酷。

【讨论】:

  • 我明白,但 LzmaCompress()LzmaDecompress() 是帮助函数,只需一次调用即可压缩/解压缩完整的数据块。
  • 那么关于MCVE的部分就剩下了。
【解决方案3】:

压缩时,将压缩输出字节数传递给调用者。但是您的缓冲区包含LZMA_PROPS_SIZE 额外的字节。因此,在编写 lzma 文件时,您实际上忘记了最后一个 LZMA_PROPS_SIZE 字节,而在以后的阅读中,这些都丢失了。

【讨论】:

  • 确实如此。我已将LZMA_PROPS_SIZE 添加到结果大小,但问题仍然存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 2023-03-16
  • 2023-03-06
  • 1970-01-01
  • 2021-05-14
  • 1970-01-01
相关资源
最近更新 更多