C 如何让LZO使用文件流?

C 如何让LZO使用文件流?,c,file,compression,stream,lzo,C,File,Compression,Stream,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压缩一个文件流,但距离不远。具体地说,在提取由我的
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);
这种方法有什么问题导致分割错误


我希望这次没有遗漏任何代码。如果需要添加更多信息,请随时通知我。提前感谢您的建议。

您给出的代码不会编译(在
#defines
infeptr
中的伪
=
,而不是在各个地方的
inFnPtr
等)。但是:

  • 压缩时,您没有考虑由
    fread()
    返回的实际数据量,这很可能小于
    LZO\u IN\u CHUNK

    compressionResult = lzo1x_1_compress(in, LZO_IN_CHUNK, out, &out_len, wrkmem);
    
    应该是

    compressionResult = lzo1x_1_compress(in, inResult, out, &out_len, wrkmem);
    
    extractionResult = lzo1x_decompress(in, inResult, out, &new_length, NULL);
    
    (这不太可能是问题所在,但会在文件末尾添加虚假垃圾。)

  • 解压时,您也会遇到类似的问题,并且in/out参数是错误的,这很可能是您的错误的原因

    extractionResult = lzo1x_decompress(out, LZO_OUT_CHUNK, in, &new_length, NULL);
    
    应该是

    compressionResult = lzo1x_1_compress(in, inResult, out, &out_len, wrkmem);
    
    extractionResult = lzo1x_decompress(in, inResult, out, &new_length, NULL);
    

  • 您正在压缩独立块。LZO解压器需要压缩数据的字节长度,因为当它解码EOF时,它会检查是否已消耗所有输入字节(如果没有,则返回一个错误),因此您还需要存储每个压缩块的长度。因此,您需要更复杂的文件格式。例如:

    # compressing, in python-like pseudocode
    ifile = open("data", "rb")
    ofile = open("data.mylzo", "wb")
    input, input_len = ifile.read(65536)
    while input_len > 0:
      compressed, compressed_len = lzo1x(input, input_len)
      compressed_len -= 1 # store len-1 of next block
      if compressed_len < 65536 - 1:
        ofile.write(compressed_len & 255) # be sure of endianess in file formats!
        ofile.write(compressed_len >> 8)
        ofile.write(compressed)
      else:
        ofile.write(255) # incompressible block stored it as-is (saves space & time).
        ofile.write(255)
        ofile.write(input)
      input, input_len = ifile.read(65536)
    ofile.close()
    ifile.close()
    
    # decompressing, in python-like pseudocode
    ifile = open("data.mylzo", "rb")
    ofile = open("data", "wb")
    compressed_len_s = ifile.read(2)
    while len(compressed_len_s) == 2:
      compressed_len = (compressed_len_s[0] | (compressed_len_s[1] << 8)) + 1
      if compressed_len == 65536:
        ofile.write(ifile.read(65536)) # this can be done without copying
      else:
        compressed = ifile.read(compressed_len)
        decompressed = lzo1x_decompress(compressed, compressed_len)
        ofile.write(decompressed)
      compressed_len_s = ifile.read(2)
    ofile.close()
    ifile.close()
    
    #压缩,类似python的伪代码
    ifile=打开(“数据”、“rb”)
    ofile=open(“data.mylzo”、“wb”)
    输入,输入长度=ifile.read(65536)
    当输入长度>0时:
    压缩,压缩长度=lzo1x(输入,输入长度)
    压缩的_len-=1#存储下一个块的len-1
    如果压缩长度<65536-1:
    ofile.write(compressed_len&255)#确保文件格式的结尾!
    ofile.write(压缩长度>>8)
    ofile.write(压缩)
    其他:
    ofile.write(255)#不可压缩块按原样存储(节省空间和时间)。
    ofile.write(255)
    ofile.write(输入)
    输入,输入长度=ifile.read(65536)
    ofile.close()
    ifile.close()
    #解压缩,使用类似python的伪代码
    ifile=open(“data.mylzo”、“rb”)
    ofile=打开(“数据”、“wb”)
    压缩长度=ifile.read(2)
    而len(压缩的len)=2:
    
    compressed_len=(compressed_len_s[0]|(compressed_len_s[1]我认为您在
    int compressFileWithLzo1x
    中打开了错误的文件:

    FILE *inFnPtr = fopen(outFn, "r");
    
    应该是

    FILE *inFnPtr = fopen(inFn, "r");
    

    我认为越来越近,但是在调用
    lzo1x\u 1\u compress()
    之前和之后执行
    fprintf()
    语句(查看
    in
    out
    缓冲区)表明文本数据没有被压缩。