2010-09-01 4 views
14

je peux trouver beaucoup de fonctions qui vous permettent de décompresser un fichier gzip, mais comment puis-je décomprimer une chaîne GZip?chaîne Décompresser GZip en Java

Je suis en train d'analyser une réponse HTTP où le corps de réponse est compressé avec gzip. Cependant, la réponse entière est simplement stockée dans une chaîne, donc une partie de la chaîne contient des caractères binaires.

Je tente d'utiliser:

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

Mais cela jette juste une exception: java.io.IOException: Non au format GZIP

Répondre

14

Il n'y a pas une telle chose comme une chaîne GZip. GZip est binaire, les chaînes sont du texte.

Si vous souhaitez compresser une chaîne, vous devez convertir d'abord en binaire - par exemple avec OutputStreamWriter enchaîné à une compression OutputStream (par exemple un GZIPOutputStream)

même de lire les données, on peut utiliser un InputStreamReader enchaîné à un décomprimer InputStream (par exemple un GZIPInputStream).

Une façon de lire facilement à partir d'un Reader est d'utiliser CharStreams.toString(Readable) de Guava, ou une bibliothèque similaire.

+0

J'essaye d'analyser une réponse HTTP où le corps de la réponse est compressé avec GZip. Cependant, la réponse entière est simplement stockée dans une chaîne, donc une partie de la chaîne contient des caractères binaires. Êtes-vous en train de dire qu'il n'est pas possible de convertir cette "chaîne GZip" en une chaîne de texte? – Matt

+0

@Matt: Vous ne devriez pas stocker la réponse dans une chaîne pour commencer. Si c'est binaire, il ne devrait pas être dans du texte, sauf s'il s'agit de base64. Le concept de "partie de la chaîne contient des données binaires" ne fonctionne vraiment pas. On dirait que vous devez changer votre approche. –

+0

La réponse est initialement présentée comme un octet [], c'est tout ce que j'ai à disposition. Puis-je l'utiliser? – Matt

1

Idéalement, vous devriez utiliser une bibliothèque de haut niveau pour gérer ce genre de choses pour vous. De cette façon, chaque fois qu'une nouvelle version de HTTP est publiée, le mainteneur de la bibliothèque fait tout le travail pour vous et vous avez juste besoin de la version mise à jour de la bibliothèque. Cela dit, c'est un bon exercice que d'essayer de le faire soi-même.

laisse supposer que vous lisez une réponse HTTP comme un flux d'octets à partir d'un socket TCP. S'il n'y avait pas d'encodage gzip, mettre toute la réponse dans une chaîne pouvait fonctionner. Cependant, la présence d'un en-tête "Content-Encoding: gzip" signifie que le corps de la réponse sera (comme vous l'avez noté) binaire.

Vous pouvez identifier le début du corps de la réponse comme le premier octet suivant la première occurrence de la séquence de chaînes "\ r \ n \ r \ n" (ou les 4 octets 0x0d, 0x0a, 0x0d, 0x0a).

L'encodage gzip a un en-tête spécial, et vous devez tester les 3 premiers octets du corps pour que:

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

L'erreur « Non au format gzip » est produit par GZIPInputStream si les 3 premiers octets ne le font pas correspondre aux valeurs d'en-tête GZIP magiques, donc le test pour ceux-ci aidera à résoudre votre problème particulier.

Il y a aussi une somme de contrôle CRC dans le format GZIP, cependant si cela est manquant ou incorrect, vous devriez voir une erreur différente.

Questions connexes