LzmaLib:压缩/解压缩 C 中的缓冲区
LzmaLib: compress / decompress buffer in C
我正在尝试使用 LzmaLib's LzmaCompress()
and LzmaDecompress()
with buffers, adapting the examples provided here。
我正在测试一个 ~3MB 的缓冲区,压缩功能似乎工作正常(产生一个 ~1.2MB 的压缩缓冲区),但是当我尝试解压缩时,它只提取了 ~300 字节和 returns 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 压缩缓冲区的更好方法,我很乐意接受建议。
我没有专门针对 LzmaCompress
检查这个,但大多数其他压缩库(如 libz)处理的功能类似于标准 read/write 或 fread/fwrite 功能,即允许您不断调用函数以在一个流中压缩越来越多的数据。所以在某些时候,你将不得不说 "I'm done, please flush everything not written so far"。可能,您忘记了那部分。如果没有,Minimal, Complete, and Verifiable example 会很酷。
压缩时,将压缩后的输出字节数传递给调用者。但是您的缓冲区包含 LZMA_PROPS_SIZE
个额外的字节。因此,在编写 lzma 文件时,您实际上忘记了最后 LZMA_PROPS_SIZE
个字节,而在稍后阅读时,这些字节丢失了。
我敢打赌问题出在您如何 read/write 您的文件中。您需要以二进制模式打开它们以防止在 read/write 操作期间进行任何替换。
更改所有实例:
fopen(xxx, "r")
-> fopen(xxx, "rb")
fopen(xxx, "w")
-> fopen(xxx, "wb")
我正在尝试使用 LzmaLib's LzmaCompress()
and LzmaDecompress()
with buffers, adapting the examples provided here。
我正在测试一个 ~3MB 的缓冲区,压缩功能似乎工作正常(产生一个 ~1.2MB 的压缩缓冲区),但是当我尝试解压缩时,它只提取了 ~300 字节和 returns 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 压缩缓冲区的更好方法,我很乐意接受建议。
我没有专门针对 LzmaCompress
检查这个,但大多数其他压缩库(如 libz)处理的功能类似于标准 read/write 或 fread/fwrite 功能,即允许您不断调用函数以在一个流中压缩越来越多的数据。所以在某些时候,你将不得不说 "I'm done, please flush everything not written so far"。可能,您忘记了那部分。如果没有,Minimal, Complete, and Verifiable example 会很酷。
压缩时,将压缩后的输出字节数传递给调用者。但是您的缓冲区包含 LZMA_PROPS_SIZE
个额外的字节。因此,在编写 lzma 文件时,您实际上忘记了最后 LZMA_PROPS_SIZE
个字节,而在稍后阅读时,这些字节丢失了。
我敢打赌问题出在您如何 read/write 您的文件中。您需要以二进制模式打开它们以防止在 read/write 操作期间进行任何替换。
更改所有实例:
fopen(xxx, "r")
->fopen(xxx, "rb")
fopen(xxx, "w")
->fopen(xxx, "wb")