2011-09-24 24 views
6

Estoy tratando de implementar las funciones desinflar e inflar zlib.h para comprimir y descomprimir una matriz de caracteres (no un archivo).desinflar e inflar (zlib.h) en C

Me gustaría saber si la siguiente sintaxis es correcta? ¿Me estoy perdiendo algo o he definido algo incorrectamente?

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

¿Lo estás preguntando porque no está funcionando? ¿Estás recibiendo algún tipo de mensaje de error? – larsks

+0

@larsks Se compila sin advertencias pero quiero saber si las funciones y definiciones que elegí tienen sentido o si debería usar otras. –

+0

Lo tengo. Gracias por aclarar tu pregunta. – larsks

Respuesta

6

No se puede imprimir la salida desinflada de esta manera. No es nulo terminado. No puedes forzarlo tampoco.

Dado que su entrada es una cadena aunque probablemente solo quiera pasar el contenido de la cadena incluyendo el terminador nulo. Establezca avail_in en strlen (a) + 1.

Debe examinar los campos next_out y avail_out después de llamar a deflate para ver cuántos datos se escribieron en el búfer de salida.

Consulte la documentación here bajo la llamada deflate.

Aquí está su código modificado. Tenga en cuenta que si está comprimiendo algo que no es una cadena, tendrá que cambiar esto y también con las cadenas, puede comprimir sin el cero de finalización y volver a agregarlo después de descomprimir.

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

El ejemplo zpipe (http://zlib.net/zpipe.c) cubre prácticamente todo, basta con retirar las operaciones de archivo (la función f prefijo), y sustituir in y out con su in- búferes de memoria, aunque puede ser suficiente reemplazar solo in o mantener los búferes tal como están, dependiendo de su uso. Sólo tenga en cuenta que tendrá que hacer su búfer cabo de tamaño variable a tener en cuenta para la descompresión de datos de tamaño arbitrario, si usted está planeando tener trozos del tamaño de desconocidos

21

zlib ya cuenta con una sencilla inflar/función se puede utilizar desinflarse.

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

En caso de duda, consulte el zlib manual. Mi código es horrible, lo siento =/

+2

+1 travieso, tal vez, pero apunta a una solución que entumece la mente, que siempre se prefiere. 'compress()' y 'uncompress()' son la forma más simple que puede obtener, y la presenta de manera más que adecuada. – WhozCraig

+2

El problema con este método de utilidad es que necesita saber de alguna manera el tamaño del contenido comprimido ...:/ – Johannes

+0

En cuyo caso puede usar sizeof() en el contenido no comprimido. Es un uso básico de los métodos compress() y uncompress(), que es un buen comienzo, pero existen técnicas más eficientes. –

Cuestiones relacionadas