2010-11-20 18 views
2

Bir dosya akışını LZO ile sıkıştırmaya ve çok uzaklaşmaya çalışmıyorum. Özellikle, compressFileWithLzo1x işlevimin oluşturduğu arşiv dosyasını ayıklarken bölümleme hatası alıyorum.LZO bir dosya akışı ile çalışmak nasıl?

Benim main fonksiyonu ve prototip bildirimleri şunlardır:

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; 
} 
: Burada
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; 
} 

benim dekompresyon fonksiyonunun uygulamasıdır: Burada
#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; 
} 

benim sıkıştırma fonksiyonu uygulamasıdır

Segmentasyon hatası burada oluşur:

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

Bölütleme hatasına neden olan bu yaklaşımda sorun nedir?

Umarım bu sefer kodum çıkmamıştır. Daha fazla bilgi eklemem gerekirse bana bildirmekten çekinmeyin. Tavsiyeniz için şimdiden teşekkür ederiz.

cevap

1

derlemek olmaz verdik kodu (#defines yılında sahte =; inFilePtr yerine çeşitli yerlerde inFnPtr, vs.). Ama:

  1. , iyi LZO_IN_CHUNK daha az olabilir fread() tarafından döndürülen verilerin gerçek miktarı, dikkate alarak değildir sıkıştırarak.

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

    muhtemelen (Bu sorun olması pek mümkün değildir, ancak dosyanın sonuna sahte önemsiz ekleyecektir.)

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

    olmalıdır

  2. açılırken, bir var benzer bir sorun, ve içeri/dışarı argümanları yanlış yoldur, bu sizin segfaultunuzun nedeni olabilir.

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

    muhtemelen

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

yaklaştıkça olmalı, sanırım, ama yapıyor 'fprintf()' öncesi ve sonrası ifadeleri ' lzo1x_1_compress() 'çağrısı (in' ve 'out' arabelleklerine bakın), metin verilerinin sıkıştırılmamasını önerir. –

2

Sen sıkıştırarak ediyoruz bağımsız bloklar olmalıdır. LZO sıkıştırıcı, sıkıştırılmış verilerin bayt uzunluğuna ihtiyaç duyar, çünkü EOF kodunu çözdüğü zaman, tüm girdi baytlarını tüketip tüketmediğini kontrol eder (ve eğer olmadıysa bir hata döndürür), böylece her sıkıştırılmış parçanın uzunluğunu da depolamanız gerekir. . Böylece daha karmaşık bir dosya formatına ihtiyacınız var. Örneğin:

# 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() 

sen atlamadan parçalarını sıkıştırmasını edebilmek istiyorsanız

(paralel ya da rastgele erişim dekompresyon için) ilk yığın önce, başlangıçta sıkıştırılmış parçalar uzunluklarının koymanız gerekir. Onları parça sayısıyla önleyin.

Son yığın 64k'dan daha kısa olabilir ve sıkıştırılamaz olabilir, ancak sıkıştırılmış formun sıkıştırılmamış formdan daha uzun olmasına rağmen depolanmaya devam eder, çünkü yalnızca 64k'lık bloklar olduğu gibi depolanır. Tüm dosya 64k'dan kısasa, büyür.

1

Sana int compressFileWithLzo1x yanlış dosyayı açıyoruz düşünüyorum:

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

o

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