compresión y descompresión de datos de cadena en java

Estoy usando el siguiente código para comprimir y descomprimir datos de cadena, pero el problema al que me estoy enfrentando es que se comprime fácilmente sin error, pero el método de descompresión arroja el siguiente error.

Excepción en el hilo “main” java.io.IOException: No en formato GZIP

public static void main(String[] args) throws Exception { String string = "I am what I am hhhhhhhhhhhhhhhhhhhhhhhhhhhhh" + "bjggujhhhhhhhhh" + "rggggggggggggggggggggggggg" + "esfffffffffffffffffffffffffffffff" + "esffffffffffffffffffffffffffffffff" + "esfekfgy enter code here`etd`enter code here wdd" + "heljwidgutwdbwdq8d" + "skdfgysrdsdnjsvfyekbdsgcu" +"jbujsbjvugsduddbdj"; System.out.println("after compress:"); String compressed = compress(string); System.out.println(compressed); System.out.println("after decompress:"); String decomp = decompress(compressed); System.out.println(decomp); } public static String compress(String str) throws Exception { if (str == null || str.length() == 0) { return str; } System.out.println("String length : " + str.length()); ByteArrayOutputStream obj=new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(obj); gzip.write(str.getBytes("UTF-8")); gzip.close(); String outStr = obj.toString("UTF-8"); System.out.println("Output String length : " + outStr.length()); return outStr; } public static String decompress(String str) throws Exception { if (str == null || str.length() == 0) { return str; } System.out.println("Input String length : " + str.length()); GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(str.getBytes("UTF-8"))); BufferedReader bf = new BufferedReader(new InputStreamReader(gis, "UTF-8")); String outStr = ""; String line; while ((line=bf.readLine())!=null) { outStr += line; } System.out.println("Output String lenght : " + outStr.length()); return outStr; } 

¡Todavía no se pudo resolver cómo solucionar este problema!

Esto es debido a

 String outStr = obj.toString("UTF-8"); 

Envíe el byte[] que puede obtener de su ByteArrayOutputStream y GZIPInputStream como tal en su ByteArrayInputStream para construir su GZIPInputStream . Los siguientes son los cambios que deben hacerse en su código.

 byte[] compressed = compress(string); //In the main method public static byte[] compress(String str) throws Exception { ... ... return obj.toByteArray(); } public static String decompress(byte[] bytes) throws Exception { ... GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes)); ... } 

La respuesta anterior resuelve nuestro problema, pero además de eso. si estamos tratando de descomprimir un byte sin comprimir (“no es un formato zip”) []. obtendremos el mensaje de excepción “No en formato GZIP”.

Para resolver eso, podemos agregar un código de adición en nuestra Clase.

 public static boolean isCompressed(final byte[] compressed) { return (compressed[0] == (byte) (GZIPInputStream.GZIP_MAGIC)) && (compressed[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8)); } 

Mi clase de compresión completa con comprimir / descomprimir se vería así:

 import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; public class GZIPCompression { public static byte[] compress(final String str) throws IOException { if ((str == null) || (str.length() == 0)) { return null; } ByteArrayOutputStream obj = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(obj); gzip.write(str.getBytes("UTF-8")); gzip.flush(); gzip.close(); return obj.toByteArray(); } public static String decompress(final byte[] compressed) throws IOException { final StringBuilder outStr = new StringBuilder(); if ((compressed == null) || (compressed.length == 0)) { return ""; } if (isCompressed(compressed)) { final GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(compressed)); final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gis, "UTF-8")); String line; while ((line = bufferedReader.readLine()) != null) { outStr.append(line); } } else { outStr.append(compressed); } return outStr.toString(); } public static boolean isCompressed(final byte[] compressed) { return (compressed[0] == (byte) (GZIPInputStream.GZIP_MAGIC)) && (compressed[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8)); } } 

Si alguna vez necesita transferir el contenido comprimido a través de la red o almacenarlo como texto, debe usar el codificador Base64 (como el códec Apache commons Base64) para convertir la matriz de bytes a una Cadena Base64 y decodificar la cadena de regreso a la matriz de bytes en cliente remoto ¡Encontré un ejemplo en Use Zip Stream y Base64 Encoder para comprimir datos de cadenas grandes !

El problema es esta línea:

  String outStr = obj.toString("UTF-8"); 

El conjunto de bytes obj contiene datos binarios arbitrarios. No puede “decodificar” datos binarios arbitrarios como si fuera UTF-8. Si lo intenta, obtendrá un String que luego no puede ser “codificado” en bytes. O al menos, los bytes que obtenga serán diferentes a los que comenzó … en la medida en que ya no sean una transmisión GZIP válida.

La solución es almacenar o transmitir el contenido de la matriz de bytes tal como está. No intentes convertirlo en una cadena. Son datos binarios, no texto.

No puede convertir datos binarios a String. Como solución, puede codificar datos binarios y luego convertirlos a String. Por ejemplo, mira esto. ¿Cómo se convierten los datos binarios a cadenas y viceversa en Java?

Otro ejemplo de compresión y descompresión correctas:

 @Slf4j public class GZIPCompression { public static byte[] compress(final String stringToCompress) { if (isNull(stringToCompress) || stringToCompress.length() == 0) { return null; } try (final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final GZIPOutputStream gzipOutput = new GZIPOutputStream(baos)) { gzipOutput.write(stringToCompress.getBytes(UTF_8)); gzipOutput.finish(); return baos.toByteArray(); } catch (IOException e) { throw new UncheckedIOException("Error while compression!", e); } } public static String decompress(final byte[] compressed) { if (isNull(compressed) || compressed.length == 0) { return null; } try (final GZIPInputStream gzipInput = new GZIPInputStream(new ByteArrayInputStream(compressed)); final StringWriter stringWriter = new StringWriter()) { IOUtils.copy(gzipInput, stringWriter, UTF_8); return stringWriter.toString(); } catch (IOException e) { throw new UncheckedIOException("Error while decompression!", e); } } }