2011-09-24 10 views
6

Sto tentando di implementare le funzioni zlib.h deflate e di gonfiare per comprimere e decomprimere un array di caratteri (non un file).sgonfiare e gonfiare (zlib.h) in C

Mi piacerebbe sapere se la seguente sintassi è corretta? Mi manca qualcosa o definito qualcosa in modo errato?

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

Stai chiedendo perché non funziona? Stai ricevendo una sorta di messaggio di errore? – larsks

+0

@larsks Compila senza avvisi ma voglio sapere se le funzioni e le definizioni che ho scelto hanno senso o se dovrei usarne altre. –

+0

Capito. Grazie per aver chiarito la tua domanda. – larsks

risposta

6

Non è possibile stampare l'output sgonfiato in questo modo. Non è terminato con null. Non puoi nemmeno stringerlo.

Poiché l'input è una stringa sebbene probabilmente si desidera solo passare il contenuto della stringa incluso il terminatore null. Quindi impostare avail_in su strlen (a) + 1.

È necessario esaminare i campi next_out e avail_out dopo aver chiamato deflate per vedere quanti dati sono stati scritti nel buffer di output.

Vedere la documentazione here sotto la chiamata deflate.

Ecco il codice modificato. Nota se stai comprimendo qualcosa che non è una stringa, dovrai modificarlo e anche con le stringhe che potresti comprimere senza lo zero finale e aggiungerlo nuovamente dopo la decompressione.

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

L'esempio zpipe (http://zlib.net/zpipe.c) copre praticamente esso, è sufficiente rimuovere l'ops di file (la f funzione di prefisso), e si sostituisce in e out con il vostro in- buffer di memoria, anche se potrebbe essere sufficiente sostituire solo in o mantenere i buffer così come sono in base all'utilizzo. Basta notare che è necessario per rendere il vostro tampone fuori ridimensionabile per tenere conto di decompressione dei dati arbitrariamente dimensioni, se si ha intenzione di avere pezzi di dimensioni sconosciute

21

zlib ha già una semplice gonfiare/funzione è possibile utilizzare sgonfiarsi.

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); 

In caso di dubbio, controllare il zlib manual. Il mio codice è scadente, mi spiace =/

+2

Forse un po 'schifoso, ma indica una soluzione che intorpidisce la mente, che è sempre preferita. 'compress()' e 'uncompress()' riguardano la forma più semplice che si può ottenere e la si presenta più che adeguatamente. – WhozCraig

+2

Il problema con questo metodo di utilità è che è necessario conoscere in qualche modo la dimensione del contenuto ucompressed ...:/ – Johannes

+0

In tal caso è possibile utilizzare sizeof() sul contenuto non compresso. È un uso basilare dei metodi compress() e uncompress(), che è un buon inizio ma esistono tecniche più efficienti. –