2010-09-01 26 views
14

Puedo encontrar muchas funciones que le permiten descomprimir un archivo GZip, pero ¿cómo descomprimo una cadena GZip?Descomprimir cadena GZip en Java

Estoy tratando de analizar una respuesta HTTP donde el cuerpo de la respuesta se comprime con GZip. Sin embargo, toda la respuesta simplemente se almacena en una cadena, por lo que parte de la cadena contiene caracteres binarios.

Estoy intentando utilizar:

byte responseBodyBytes[] = responseBody.getBytes(); 
ByteArrayInputStream bais = new ByteArrayInputStream(responseBodyBytes); 
GZIPInputStream gzis = new GZIPInputStream(bais); 

Pero eso produce una excepción: java.io.IOException: no en formato GZIP

Respuesta

14

No hay tal cosa como una cadena gzip. GZip es binario, las cadenas son texto.

Si desea comprimir una cadena, primero debe convertirla en formato binario, p. con OutputStreamWriter encadenado a una compresión OutputStream (por ejemplo, un GZIPOutputStream)

mismo modo a leer los datos, se puede utilizar un InputStreamReader encadenado a una descompresión de InputStream (por ejemplo, un GZIPInputStream).

Una forma de leer fácilmente desde Reader es usar CharStreams.toString(Readable) en Guava, o una biblioteca similar.

+0

Estoy tratando de analizar una respuesta HTTP donde el cuerpo de la respuesta se comprime con GZip. Sin embargo, toda la respuesta simplemente se almacena en una cadena, por lo que parte de la cadena contiene caracteres binarios. ¿Estás diciendo que no es posible convertir esta "cadena GZip" en una cadena de texto? – Matt

+0

@Matt: para empezar, no debe almacenar la respuesta en una cadena. Si es binario, no debería estar en ningún texto, a menos que sea base64. El concepto de "parte de la cadena contiene datos binarios" realmente no funciona. Parece que necesitas cambiar tu enfoque. –

+0

La respuesta se presenta inicialmente como un byte [], así que eso es todo lo que tengo disponible. ¿Podría usar esto? – Matt

1

Idealmente, debe utilizar una biblioteca de alto nivel para manejar estas cosas por usted. De esta forma, cada vez que se lanza una nueva versión de HTTP, el mantenedor de la biblioteca con suerte hace todo el trabajo por usted y solo necesita la versión actualizada de la biblioteca.

Aparte de eso, es un buen ejercicio intentar hacerlo usted mismo.

Supongamos que está leyendo una Respuesta HTTP como una secuencia de bytes desde un socket TCP. Si no hubiera codificación gzip, entonces poner toda la respuesta en una Cadena podría funcionar. Sin embargo, la presencia de un encabezado "Content-Encoding: gzip" significa que el cuerpo de la respuesta será (como usted notó) binario.

Puede identificar el inicio del cuerpo de respuesta como el primer byte después de la primera aparición de la secuencia de cadenas "\ r \ n \ r \ n" (o los 4 bytes 0x0d, 0x0a, 0x0d, 0x0a).

La codificación gzip tiene una cabecera especial, y usted debe probar los 3 primeros bytes del cuerpo para ello:

   byte[] buf; // from the HTTP Response stream 
       // ... insert code here to populate buf from HTTP Response stream 
       // ... 
       int bodyLen = 1234; // populate this value from 'Content-length' header 
       int bodyStart = 123; // index of byte buffer where body starts 
       if (bodyLen > 4 && buf[bodyStart] == 0x1f && buf[bodyStart + 1] == (byte) 0x8b && buf[bodyStart + 2] == 0x08) { 
        // gzip compressed body 
        ByteArrayInputStream bais = new ByteArrayInputStream(buf); 
        if (bodyStart > 0) bais.skip(bodyStart); 

        // Decompress the bytes 
        byte[] decompressedBytes = new byte[bodyLen * 4]; 
        int decompressedDataLength = 0; 
        try { 
         // note: replace this try-catch with try-with-resources here where possible 
         GZIPInputStream gzis = new GZIPInputStream(bais); 
         decompressedDataLength = gzis.read(decompressedBytes); 
         gzis.close(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
       } 

El "no en formato GZIP" error se produce por GZIPInputStream si los primeros 3 bytes no lo hacen haga coincidir los valores mágicos del encabezado GZIP, por lo que probarlos ayudará a resolver su problema en particular.

También hay una suma de comprobación CRC dentro del formato GZIP; sin embargo, si eso falta o es incorrecto, debería aparecer un error diferente.

Cuestiones relacionadas