2016-11-22 20 views
8

Tôi đang cố gắng sử dụng LzmaLib 'LzmaCompress()LzmaDecompress() với bộ đệm, điều chỉnh các ví dụ được cung cấp here.LzmaLib: đệm nén/giải nén trong C

Tôi đang thử nghiệm với bộ đệm ~ 3MB và chức năng nén dường như hoạt động tốt (tạo bộ đệm nén 1,2MB), nhưng khi tôi cố gắng giải nén, nó chỉ trích xuất ~ 300 byte và trả về SZ_ERROR_DATA.

Một vài byte được trích xuất là đúng, nhưng tôi không biết tại sao nó dừng lại ở đó.

Mã của tôi:

#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; 
} 

Nếu mã này không phải là cách tốt hơn để nén bộ đệm với LzmaLib, tôi rất vui khi chấp nhận lời đề nghị.

+0

tôi vượt qua 'dstLen' và vấn đề vẫn còn. Chỉ có một vài byte được giải nén và lỗi 1 ('SZ_ERROR_DATA') được trả về. – karliwson

Trả lời

8

Tôi đặt cược vấn đề ẩn nấp trong cách bạn đọc/ghi tệp của mình. Bạn cần phải mở chúng trong chế độ nhị phân để ngăn chặn bất kỳ thay thế nào trong quá trình đọc/ghi.

Thay đổi tất cả các trường hợp:

  • fopen(xxx, "r") ->fopen(xxx, "rb")
  • fopen(xxx, "w") ->fopen(xxx, "wb")
+0

Người đàn ông, tôi không thể nói những từ tôi đang nghĩ ngay bây giờ. Đó là vấn đề chính xác. Cảm ơn nhiều. – karliwson

+0

Những sai lầm nhỏ khó tìm nhất :) – Codeguard

0

Tôi không kiểm tra điều này cụ thể cho LzmaCompress nhưng hầu hết các thư viện nén khác như libz xử lý chức năng tương tự như chức năng đọc/ghi hoặc fread/fwrite chuẩn, tức là cho phép bạn liên tục gọi các hàm để nén nhiều hơn và nhiều dữ liệu hơn trong một luồng. Vì vậy, tại một số điểm, bạn sẽ phải nói "Tôi đã làm xong, hãy tuôn ra mọi thứ không được viết cho đến nay". Có thể, bạn quên phần đó. Nếu không, Minimal, Complete, and Verifiable example sẽ rất tuyệt.

+0

Tôi hiểu, nhưng 'LzmaCompress()' và 'LzmaDecompress()' là các hàm trợ giúp nén/giải nén toàn bộ khối dữ liệu với một cuộc gọi duy nhất. – karliwson

+0

sau đó phần về MCVE vẫn còn. –

0

Khi bạn nén, bạn chuyển số byte đầu ra đã nén cho người gọi. Nhưng bộ đệm của bạn chứa LZMA_PROPS_SIZE byte bổ sung. Vì vậy, khi viết tệp lzma, bạn thực sự quên các byte LZMA_PROPS_SIZE cuối cùng và sau đó đọc, những thứ đó bị thiếu.

+0

Đó là sự thật. Tôi đã thêm 'LZMA_PROPS_SIZE' vào kích thước kết quả nhưng vấn đề vẫn tồn tại. – karliwson