2010-11-20 13 views
2

LZO를 사용하여 파일 스트림을 압축하려고하는데 아주 멀지 않습니다. 특히, 내 compressFileWithLzo1x 함수로 만든 아카이브 파일을 추출 할 때 세그먼트 화 오류가 발생합니다.LZO를 파일 스트림과 함께 사용하려면 어떻게해야합니까?

main 기능과 프로토 타입 선언은 다음과 같습니다

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; 
} 
: 여기
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; 
} 

내 압축 해제 기능의 구현 : 여기에
#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; 
} 

내 압축 기능의 구현

분할 오류는 여기에서 발생합니다 :

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

세그멘테이션 오류를 일으키는이 방법에 어떤 문제가 있습니까?

이번에는 코드를 남기지 않았 으면합니다. 더 많은 정보를 추가해야하는 경우 알려 주시기 바랍니다. 조언 해 주셔서 미리 감사드립니다.

답변

1

제공된 코드는 컴파일되지 않습니다 (=#defines, inFilePtrinFnPtr이 아닌 여러 위치 등). 그러나 :

  1. , 당신이 잘 LZO_IN_CHUNK 미만 수도 fread()에 의해 반환 된 데이터의 실제 양을 고려하지 않는 압축.

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

    아마 (이 문제가 될 것 같지이지만, 파일의 끝에 가짜 쓰레기를 추가합니다.)

    compressionResult = lzo1x_1_compress(in, inResult, out, &out_len, wrkmem); 
    

    해야

  2. 압축 해제, 당신은이 비슷한 문제가 인/아웃 인수가 잘못된 방법 라운드, 당신의 segfault의 원인이 될 가능성이 높습니다.

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

    아마

    extractionResult = lzo1x_decompress(in, inResult, out, &new_length, NULL); 
    
+0

가까이 얻기해야한다, 나는 생각하지만, 일을'는 fprintf()'전후 문장은' lzo1x_1_compress()'호출 ('in'과'out' 버퍼를 보임)은 텍스트 데이터가 압축되지 않는다는 것을 나타냅니다. –

2

당신은 압축하고 독립적 인 블록이어야한다. 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() 

당신이 건너 뛰는없이 덩어리의 압축을 해제 할 수있게하려면

(중 병렬 또는 랜덤 액세스에서 압축 해제) 첫 번째 덩어리 전에 시작 부분에 압축 된 덩어리의 길이를 배치해야합니다. 그들 앞에 덩어리의 수를 둡니다.

마지막 청크는 64k보다 짧을 수 있으며 압축 할 수는 없지만 전체 64k 블록 만있는 상태로 저장되기 때문에 압축되지 않은 양식보다 더 길더라도 압축 된 양식은 계속 저장합니다. 전체 파일이 64k보다 짧으면 확장됩니다.

1

난 당신 int compressFileWithLzo1x에 잘못된 파일을 열 생각 :

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

그것이

FILE *inFnPtr = fopen(inFn, "r"); 
관련 문제