如何让 LZO 处理文件流?
我正在尝试使用 LZO 压缩文件流,但效果不佳。具体来说,在提取 compressFileWithLzo1x
函数创建的存档文件时出现分段错误。
我的 main
函数和原型声明是:
#include <stdio.h>
#include <stdlib.h>
#include "lzo/include/lzo/lzo1x.h"
#define LZO_IN_CHUNK (128*1024L)
#define LZO_OUT_CHUNK (LZO_IN_CHUNK + LZO_IN_CHUNK/16 + 64 + 3)
int compressFileWithLzo1x(const char *inFn, const char *outFn);
int extractFileWithLzo1x(const char *inFn);
int main(int argc, char **argv) {
const char *inFilename = "test.txt";
const char *outFilename = "test.txt.lzo1x";
if ( compressFileWithLzo1x(inFilename, outFilename) != 0 )
exit(EXIT_FAILURE);
if ( extractFileWithLzo1x(outFilename) != 0 )
exit(EXIT_FAILURE);
return 0;
}
这是我的压缩函数的实现:
int compressFileWithLzo1x(const char *inFn, const char *outFn) {
FILE *inFnPtr = fopen(outFn, "r");
FILE *outFnPtr = fopen(outFn, "wb");
int compressionResult;
lzo_bytep in;
lzo_bytep out;
lzo_voidp wrkmem;
lzo_uint out_len;
size_t inResult;
if (lzo_init() != LZO_E_OK)
return -1;
in = (lzo_bytep)malloc(LZO_IN_CHUNK);
out = (lzo_bytep)malloc(LZO_OUT_CHUNK);
wrkmem = (lzo_voidp)malloc(LZO1X_1_MEM_COMPRESS);
do {
inResult = fread(in, sizeof(lzo_byte), LZO_IN_CHUNK, inFnPtr);
if (inResult == 0)
break;
compressionResult = lzo1x_1_compress(in, LZO_IN_CHUNK, out, &out_len, wrkmem);
if ((out_len >= LZO_IN_CHUNK) || (compressionResult != LZO_E_OK))
return -1;
if (fwrite(out, sizeof(lzo_byte), (size_t)out_len, outFnPtr) != (size_t)out_len || ferror(outFnPtr))
return -1;
fflush(outFnPtr);
} while (!feof(inFnPtr) && !ferror(inFnPtr));
free(wrkmem);
free(out);
free(in);
fclose(inFnPtr);
fclose(outFnPtr);
return 0;
}
这是我的解压缩函数的实现:
int extractFileWithLzo1x(const char *inFn) {
FILE *inFnPtr = fopen(inFn, "rb");
lzo_bytep in = (lzo_bytep)malloc(LZO_IN_CHUNK);
lzo_bytep out = (lzo_bytep)malloc(LZO_OUT_CHUNK);
int extractionResult;
size_t inResult;
lzo_uint new_length;
if (lzo_init() != LZO_E_OK)
return -1;
do {
new_length = LZO_IN_CHUNK;
inResult = fread(in, sizeof(lzo_byte), LZO_IN_CHUNK, inFnPtr);
extractionResult = lzo1x_decompress(out, LZO_OUT_CHUNK, in, &new_length, NULL);
if ((extractionResult != LZO_E_OK) || (new_length != LZO_IN_CHUNK))
return -1;
fprintf(stderr, "out: [%s]\n", (unsigned char *)out);
} while (!feof(inFnPtr) && (!ferror(inFnPtr));
free(in);
free(out);
fclose(inFnPtr);
return 0;
}
分段错误发生在这里:
extractionResult = lzo1x_decompress(out, LZO_OUT_CHUNK, in, &new_length, NULL);
这种导致分段的方法有什么问题过错?
我希望这次我没有遗漏任何代码。如果我需要添加更多信息,请随时告诉我。预先感谢您的建议。
I am trying to compress a file stream with LZO and not getting very far. Specifically, I get a segmentation fault when extracting the archive file created by my compressFileWithLzo1x
function.
My main
function and prototype declarations are:
#include <stdio.h>
#include <stdlib.h>
#include "lzo/include/lzo/lzo1x.h"
#define LZO_IN_CHUNK (128*1024L)
#define LZO_OUT_CHUNK (LZO_IN_CHUNK + LZO_IN_CHUNK/16 + 64 + 3)
int compressFileWithLzo1x(const char *inFn, const char *outFn);
int extractFileWithLzo1x(const char *inFn);
int main(int argc, char **argv) {
const char *inFilename = "test.txt";
const char *outFilename = "test.txt.lzo1x";
if ( compressFileWithLzo1x(inFilename, outFilename) != 0 )
exit(EXIT_FAILURE);
if ( extractFileWithLzo1x(outFilename) != 0 )
exit(EXIT_FAILURE);
return 0;
}
Here is the implementation of my compression function:
int compressFileWithLzo1x(const char *inFn, const char *outFn) {
FILE *inFnPtr = fopen(outFn, "r");
FILE *outFnPtr = fopen(outFn, "wb");
int compressionResult;
lzo_bytep in;
lzo_bytep out;
lzo_voidp wrkmem;
lzo_uint out_len;
size_t inResult;
if (lzo_init() != LZO_E_OK)
return -1;
in = (lzo_bytep)malloc(LZO_IN_CHUNK);
out = (lzo_bytep)malloc(LZO_OUT_CHUNK);
wrkmem = (lzo_voidp)malloc(LZO1X_1_MEM_COMPRESS);
do {
inResult = fread(in, sizeof(lzo_byte), LZO_IN_CHUNK, inFnPtr);
if (inResult == 0)
break;
compressionResult = lzo1x_1_compress(in, LZO_IN_CHUNK, out, &out_len, wrkmem);
if ((out_len >= LZO_IN_CHUNK) || (compressionResult != LZO_E_OK))
return -1;
if (fwrite(out, sizeof(lzo_byte), (size_t)out_len, outFnPtr) != (size_t)out_len || ferror(outFnPtr))
return -1;
fflush(outFnPtr);
} while (!feof(inFnPtr) && !ferror(inFnPtr));
free(wrkmem);
free(out);
free(in);
fclose(inFnPtr);
fclose(outFnPtr);
return 0;
}
Here is the implementation of my decompression function:
int extractFileWithLzo1x(const char *inFn) {
FILE *inFnPtr = fopen(inFn, "rb");
lzo_bytep in = (lzo_bytep)malloc(LZO_IN_CHUNK);
lzo_bytep out = (lzo_bytep)malloc(LZO_OUT_CHUNK);
int extractionResult;
size_t inResult;
lzo_uint new_length;
if (lzo_init() != LZO_E_OK)
return -1;
do {
new_length = LZO_IN_CHUNK;
inResult = fread(in, sizeof(lzo_byte), LZO_IN_CHUNK, inFnPtr);
extractionResult = lzo1x_decompress(out, LZO_OUT_CHUNK, in, &new_length, NULL);
if ((extractionResult != LZO_E_OK) || (new_length != LZO_IN_CHUNK))
return -1;
fprintf(stderr, "out: [%s]\n", (unsigned char *)out);
} while (!feof(inFnPtr) && (!ferror(inFnPtr));
free(in);
free(out);
fclose(inFnPtr);
return 0;
}
The segmentation fault occurs here:
extractionResult = lzo1x_decompress(out, LZO_OUT_CHUNK, in, &new_length, NULL);
What is wrong with this approach that is causing the segmentation fault?
I hope I haven't left any code out this time. Feel free to let me know if I need to add more information. Thanks in advance for your advice.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您正在压缩独立的块。 LZO 解压缩器需要压缩数据的字节长度,因为当它解码 EOF 时,它会检查是否已消耗所有输入字节(如果没有,则返回错误),因此您还需要存储每个压缩块的长度。因此您需要更复杂的文件格式。例如:
如果您希望能够解压缩块而不跳过(无论是并行解压缩还是随机访问),您应该将压缩块的长度放在第一个块之前的开头。在它们前面加上块的数量。
最后一个块可以短于 64k,并且它可以是不可压缩的,但我们仍然会存储压缩形式,即使它比非压缩形式长,因为只有完整的 64k 块按原样存储。如果整个文件小于 64k,它将增长。
You're compressing independent blocks. The LZO decompressor needs the byte length of the compressed data because when it decodes EOF it checks whether it has consumed all the input bytes (and returns an error if it hasn't) so you need to store the length of each compressed chunk as well. Thus you need a more complex file format. For example:
If you want to be able to decompress the chunks without skipping (either for decompression in parallel or random access) you should place the lengths of compressed chunks at the beginning, before the first chunk. Precede them with the number of chunks.
The last chunk can be shorter than 64k, and it can be incompressible but we'll still store the compressed form, even though it's longer than the non-compressed form, because only full 64k blocks are stored as-is. If entire file is shorter than 64k, it will grow.
您给出的代码将无法编译(
#defines
中的虚假=
;inFilePtr
而不是inFnPtr
各地等)。但是:压缩时,您没有考虑
fread()
返回的实际数据量,它很可能小于LZO_IN_CHUNK
。 p>应该是
(这不太可能是问题,但会在文件末尾添加虚假垃圾。)
解压缩时,您遇到类似的问题,和输入/输出参数是错误的方式,这可能是您的段错误的原因。
应该是
The code you've given won't compile (spurious
=
in the#defines
;inFilePtr
instead ofinFnPtr
in various places, etc.). But:When compressing, you are not taking account of the actual amount of data returned by the
fread()
, which might well be less thanLZO_IN_CHUNK
.should probably be
(This is unlikely to be the problem, but will add bogus junk at the end of the file.)
When decompressing, you have a similar problem, and the in / out arguments are the wrong way round, which is likely to be the cause of your segfault.
should probably be
我认为您在
int compressFileWithLzo1x
中打开了错误的文件:它应该是
I think you are opening the wrong file in
int compressFileWithLzo1x
:it should be