2011-09-24 15 views
6

Próbuję zaimplementować deflate zlib.h i nadmuchać funkcje, aby skompresować i rozpakować tablicę znaków (a nie plik).deflate and inflate (zlib.h) in C

Chciałbym wiedzieć, czy poniższa składnia jest poprawna? Czy brakuje czegoś lub zdefiniowałem coś niepoprawnie?

char a[50] = "Hello World!"; 
char b[50]; 
char c[50]; 

// deflate 
// zlib struct 
z_stream defstream; 
defstream.zalloc = Z_NULL; 
defstream.zfree = Z_NULL; 
defstream.opaque = Z_NULL; 
defstream.avail_in = (uInt)sizeof(a); // size of input 
defstream.next_in = (Bytef *)a; // input char array 
defstream.avail_out = (uInt)sizeof(b); // size of output 
defstream.next_out = (Bytef *)b; // output char array 

deflateInit(&defstream, Z_DEFAULT_COMPRESSION); 
deflate(&defstream, Z_FINISH); 
deflateEnd(&defstream); 

printf("Deflate:\n%lu\n%s\n", strlen(b), b); 

// inflate 
// zlib struct 
z_stream infstream; 
infstream.zalloc = Z_NULL; 
infstream.zfree = Z_NULL; 
infstream.opaque = Z_NULL; 
infstream.avail_in = (uInt)sizeof(b); // size of input 
infstream.next_in = (Bytef *)b; // input char array 
infstream.avail_out = (uInt)sizeof(c); // size of output 
infstream.next_out = (Bytef *)c; // output char array 

inflateInit(&infstream); 
inflate(&infstream, Z_NO_FLUSH); 
inflateEnd(&infstream); 

printf("Inflate:\n%lu\n%s\n", strlen(c), c); 
+0

Czy pytasz, ponieważ nie działa? Czy otrzymujesz komunikat o błędzie? – larsks

+0

@larsks Kompiluje bez ostrzeżeń, ale chcę wiedzieć, czy wybrane przeze mnie funkcje i definicje mają sens, czy też powinienem używać innych. –

+0

Rozumiem. Dziękuję za wyjaśnienie Twojego pytania. – larsks

Odpowiedz

6

Nie można wydrukować tak deflowanego pliku wyjściowego. To nie jest zakończone null. Nie możesz też tego obedrzeć.

Ponieważ twoje dane wejściowe są ciągami, chociaż prawdopodobnie chcesz tylko przekazać zawartość ciągu zawierającego terminator o wartości NULL. Więc ustaw avail_in na strlen (a) + 1.

Musisz sprawdzić pola next_out i avail_out po wywołaniu deflate, aby zobaczyć, ile danych zapisano w buforze wyjściowym.

Zobacz dokumentację here pod wywołaniem deflate.

Oto zmodyfikowany kod. Zauważ, że jeśli kompresujesz coś, co nie jest ciągiem, musisz to zmienić, a także za pomocą łańcuchów, które możesz skompresować bez zera kończącego i dodać je po dekompresji.

char a[50] = "Hello World!"; 
char b[50]; 
char c[50]; 

// deflate 
// zlib struct 
z_stream defstream; 
defstream.zalloc = Z_NULL; 
defstream.zfree = Z_NULL; 
defstream.opaque = Z_NULL; 
defstream.avail_in = (uInt)strlen(a)+1; // size of input, string + terminator 
defstream.next_in = (Bytef *)a; // input char array 
defstream.avail_out = (uInt)sizeof(b); // size of output 
defstream.next_out = (Bytef *)b; // output char array 

deflateInit(&defstream, Z_DEFAULT_COMPRESSION); 
deflate(&defstream, Z_FINISH); 
deflateEnd(&defstream); 

// This is one way of getting the size of the output 
printf("Deflated size is: %lu\n", (char*)defstream.next_out - b); 

// inflate 
// zlib struct 
z_stream infstream; 
infstream.zalloc = Z_NULL; 
infstream.zfree = Z_NULL; 
infstream.opaque = Z_NULL; 
infstream.avail_in = (uInt)((char*)defstream.next_out - b); // size of input 
infstream.next_in = (Bytef *)b; // input char array 
infstream.avail_out = (uInt)sizeof(c); // size of output 
infstream.next_out = (Bytef *)c; // output char array 

inflateInit(&infstream); 
inflate(&infstream, Z_NO_FLUSH); 
inflateEnd(&infstream); 

printf("Inflate:\n%lu\n%s\n", strlen(c), c); 
2

zpipe przykład (http://zlib.net/zpipe.c) dość dużo obejmuje, po prostu usuń plik OPS (f funkcję prefiksem) i zastąpić in i out z wlotami bufory pamięci, ale może wystarczy zastąpić tylko in lub zachować bufory w takiej postaci, w jakiej są używane. Wystarczy pamiętać, że trzeba będzie dokonać bufor się resizeable celu uwzględnienia dekompresji danych arbitralnie wielkości, jeśli planujesz posiadania nieznanych wielkości kawałki

21

zlib już prostą inflate/funkcji można użyć opróżnić.

char a[50] = "Hello, world!"; 
char b[50]; 
char c[50]; 

uLong ucompSize = strlen(a)+1; // "Hello, world!" + NULL delimiter. 
uLong compSize = compressBound(ucompSize); 

// Deflate 
compress((Bytef *)b, &compSize, (Bytef *)a, ucompSize); 

// Inflate 
uncompress((Bytef *)c, &ucompSize, (Bytef *)b, compSize); 

Jeśli masz wątpliwości, sprawdź numer zlib manual. Mój kod jest brzydki, przepraszam =/

+2

+1 może być głupia, ale wskazuje na oszałamiające rozwiązanie, które zawsze jest preferowane. 'compress()' i 'uncompress()' są najprostszą formą, jaką możesz uzyskać, i przedstawiasz ją bardziej niż odpowiednio. – WhozCraig

+2

Problem z tą metodą-narzędziem polega na tym, że musisz w jakiś sposób znać rozmiar skompresowanej treści ...:/ – Johannes

+0

W takim przypadku możesz użyć sizeof() na nieskompresowanej zawartości. Jest to podstawowe użycie metod compress() i uncompress(), co jest dobrym początkiem, ale istnieją bardziej wydajne techniki. –