сжатие и декомпрессия строковых данных в java

Я использую следующий код для сжатия и распаковки строковых данных, но проблема, с которой я столкнулась, заключается в том, что она легко сжимается без ошибок, но метод распаковки вызывает следующую ошибку.

Исключение в streamе «main» java.io.IOException: не в формате 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; } 

Все еще не мог понять, как исправить эту проблему !!!

Это из-за

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

Отправьте byte[] который вы можете получить из своего ByteArrayOutputStream и используйте его как таковой в вашем ByteArrayInputStream для создания вашего GZIPInputStream . Ниже перечислены изменения, которые необходимо выполнить в вашем коде.

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

Вышеупомянутый ответ решает нашу проблему, но в дополнение к этому. если мы пытаемся распаковать несжатый («не zip-формат») байт []. мы получим сообщение об ошибке «Not in GZIP format».

Для решения этого вопроса мы можем добавить код добавления в нашем classе.

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

Мой полный class сжатия с сжатием / распаковкой будет выглядеть так:

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

Если вам когда-либо понадобится переносить сжатый контент через сеть или хранить его в виде текста, вам необходимо использовать кодировщик Base64 (например, apache commons codec Base64), чтобы преобразовать массив байтов в строку Base64 и декодировать строку обратно в массив байтов в удаленный клиент. Нашел пример использования Zip Stream и Base64 Encoder для сжатия больших строковых данных !

Проблема в этой строке:

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

Байт-массив obj содержит произвольные двоичные данные. Вы не можете «декодировать» произвольные двоичные данные, как если бы это был UTF-8. Если вы попробуете, вы получите строку, которая затем не может быть «закодирована» обратно в байты. Или, по крайней мере, полученные вами байты будут отличаться от того, с чего вы начали … в той мере, в какой они больше не являются допустимым streamом GZIP.

Исправление состоит в том, чтобы сохранить или передать содержимое массива байтов как есть. Не пытайтесь преобразовать его в строку. Это двоичные данные, а не текст.

Вы не можете преобразовать двоичные данные в String. В качестве решения вы можете кодировать двоичные данные, а затем преобразовывать в String. Например, посмотрите на это. Как преобразовать двоичные данные в строки и обратно в Java?

Другой пример правильного сжатия и декомпрессии:

 @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); } } } 
  • Как изменить цвет фона JTabbedPane?
  • В JDK 1.8 отображается искажение качания, исправлено в JDK 1.7
  • Эффективное квантование цвета gif / изображения?
  • Как получить HttpServletRequest в моих весенних бобах?
  • SQLException: Не найдено подходящего драйвера для jdbc: derby: // localhost: 1527
  • Каков размер логической переменной в Java?
  • Отражение Java: упорядочен ли порядок полей и методов classа?
  • Являются ли Spring MVC Controllers Singletons?
  • JPA - сохранение отношения от одного до большого
  • NullPointerException в invokeLater при запуске через Java Webstart
  • Java Calendar.set (Calendar.DAY_OF_WEEK, Calendar.WUNDAY), будет ли он откатываться назад, вперед или неизвестно?
  • Interesting Posts

    Где я могу разместить папку «assets» в Android Studio?

    Обработка элемента меню Click Event – Android

    Почему обращается к TextView fragmentа внутри операции, вызывая ошибку

    Как удалить метаданные всех файлов в папке и вложенных папках?

    Автоматизировать передачу файла scp с использованием сценария оболочки

    Улей: лучший способ сделать инкрементные обновления на главной таблице

    Изменение разрешения экрана гостевого экрана MacOS X для VirtualBox

    Сериализовать словарь как массив (пар ключей)

    Как автокапитализировать первый символ в поле ввода в AngularJS?

    Ошибка ContextSwitchDeadlock была обнаружена в C #

    Манипулирование базы данных Access с Java без ODBC

    Есть ли способ навести курсор на один элемент и повлиять на другой элемент?

    В чем разница между каскадом и инверсией в спящем режиме, для чего они используются?

    Android Studio работает медленно (как ускорить)?

    Отключить ключ отключения на моей клавиатуре?

    Давайте будем гением компьютера.