Как сжать строку в Java?

Я использую GZIPOutputStream или ZIPOutputStream для сжатия String (мой string.length() меньше 20), но сжатый результат длиннее исходной строки.

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

так, может ли кто-нибудь помочь мне сжать строку?

Моя функция:

 String compress(String original) throws Exception { } 

Обновить:

 import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.GZIPOutputStream; import java.util.zip.*; //ZipUtil public class ZipUtil { public static String compress(String str) { if (str == null || str.length() == 0) { return str; } ByteArrayOutputStream out = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(out); gzip.write(str.getBytes()); gzip.close(); return out.toString("ISO-8859-1"); } public static void main(String[] args) throws IOException { String string = "admin"; System.out.println("after compress:"); System.out.println(ZipUtil.compress(string)); } } 

Результат:

alt text

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

Сжатие строки длиной всего 20 символов не слишком просто, и это не всегда возможно. Если у вас есть повторение, кодирование Хаффмана или простое кодирование во время выполнения могут сжимать, но, вероятно, не очень.

Когда вы создаете String, вы можете думать о нем как о списке символов, это означает, что для каждого символа в вашей String вам необходимо поддерживать все возможные значения char. Из солнечных документов

char : Тип данных char – это один 16-разрядный символ Unicode. Он имеет минимальное значение ‘\ u0000’ (или 0) и максимальное значение ‘\ uffff’ (или 65535 включительно).

Если у вас есть уменьшенный набор символов, которые вы хотите поддержать, вы можете написать простой алгоритм сжатия, который аналогичен преобразованию двоичного -> десятичного -> шестнадцатеричного радиуса. Вы переходите от 65 536 (или сколько угодно символов поддерживает ваша целевая система) до 26 (в алфавитном порядке) / 36 (буквенно-цифровой) и т. Д.

Я использовал этот трюк несколько раз, например, временные метки кодирования в виде текста (цель 36 +, источник 10) – просто убедитесь, что у вас много модульных тестов!

Если пароли более или менее «случайные», вам не повезло, вы не сможете добиться значительного уменьшения размера.

Но: зачем вам нужно сжимать пароли? Может быть, вам не нужна компрессия, а какая-то hash-ценность? Если вам просто нужно проверить, соответствует ли имя указанному паролю, вам не нужно сохранять пароль, но можете сохранить hash пароля. Чтобы проверить, соответствует ли введенный пароль заданному имени, вы можете построить hash-значение таким же образом и сравнить его с сохраненным хешем. Поскольку hash (Object.hashCode ()) является int, вы сможете хранить все 20 паролей-hashей в 80 байт).

Ваш друг прав. Оба gzip и ZIP основаны на DEFLATE . Это алгоритм общего назначения и не предназначен для кодирования небольших строк.

Если вам это нужно, возможным решением является пользовательское кодирование и декодирование HashMap . Это может позволить вам сделать простое сопоставление «один-к-одному»:

 HashMap toCompressed, toUncompressed; String compressed = toCompressed.get(uncompressed); // ... String uncompressed = toUncompressed.get(compressed); 

Ясно, что для этого требуется настройка, и она применима только для небольшого числа строк.

Кодирование Хаффмана может помочь, но только если у вас много частых персонажей в вашей маленькой Строке

Алгоритм ZIP представляет собой комбинацию деревьев LZW и Huffman . Вы можете использовать один из этих алгоритмов отдельно.

Сжатие основывается на двух факторах:

  • повторение подстрок в вашей оригинальной цепочке (LZW): если есть много повторений, сжатие будет эффективным. Этот алгоритм имеет хорошие характеристики для сжатия длинного открытого текста, поскольку слова часто повторяются
  • число каждого символа в сжатой цепочке (Хаффман): больше перераспределение между символами несбалансировано, больше сжатие будет эффективным

В вашем случае вы должны попробовать только алгоритм LZW. В основном, цепочка может быть сжата без добавления метаинформации: возможно, это лучше для сжатия коротких строк.

Для алгоритма Хаффмана дерево кодирования должно быть отправлено со сжатым текстом. Таким образом, для небольшого текста результат может быть больше исходного текста из-за дерева.

Кодирование Хаффмана – разумный вариант здесь. Gzip и друзья делают это, но способ, которым они работают, состоит в том, чтобы построить дерево Хаффмана для ввода, отправить это, а затем отправить данные, закодированные с помощью дерева. Если дерево велико по отношению к данным, размер файла не может быть сохранен.

Тем не менее, можно избежать отправки дерева: вместо этого вы соглашаетесь, что отправитель и получатель уже имеют один. Он не может быть создан специально для каждой строки, но вы можете иметь одно глобальное дерево, используемое для кодирования всех строк. Если вы построите его с того же языка, что и входные строки (на английском или любом другом), вы все равно получите хорошее сжатие, хотя и не так хорошо, как с пользовательским деревом для каждого ввода.

Если вы знаете, что ваши строки в основном ASCII, вы можете конвертировать их в UTF-8.

 byte[] bytes = string.getBytes("UTF-8"); 

Это может уменьшить объем памяти примерно на 50%. Однако вы получите массив байтов, а не строку. Если вы пишете это в файл, это не должно быть проблемой.

Чтобы преобразовать обратно в строку:

 private final Charset UTF8_CHARSET = Charset.forName("UTF-8"); ... String s = new String(bytes, UTF8_CHARSET); 

Вы не видите никакого сжатия для своей строки. Поскольку вам по крайней мере требуется несколько сотен байт для реального сжатия с использованием GZIPOutputStream или ZIPOutputStream. Ваша строка слишком мала (я не понимаю, зачем вам требуется сжатие для того же самого)

Проверить Заключение из этой статьи :

В статье также показано, как сжимать и распаковывать данные «на лету», чтобы снизить сетевой трафик и повысить производительность ваших клиентских / серверных приложений. Тем не менее, сжатие данных «на лету» улучшает производительность клиент-серверных приложений только тогда, когда сжатые объекты составляют более нескольких сотен байт. Вы не сможете наблюдать улучшение производительности, если объекты, которые сжимаются и передаются, являются простыми объектами String, например.

Взгляните на алгоритм Хаффмана.

https://codereview.stackexchange.com/questions/44473/huffman-code-implementation

Идея состоит в том, что каждый символ заменяется последовательностью бит, в зависимости от их частоты в тексте (чем чаще, тем меньше последовательность).

Вы можете прочитать весь текст и построить таблицу кодов, например:

Код символа

0

с 10

e 110

м 111

Алгоритм строит дерево символов на основе ввода текста. Чем больше у вас персонажей, тем хуже будет сжатие.

Но в зависимости от вашего текста это может быть эффективным.

  • Ошибка при попытке извлечь файлы из zip-файла
  • 7-Zip не запрашивает у меня пароль для ZIP-файла, который я зашифровал, дважды щелкнув его
  • Как взломать защищенный паролем zip-файл
  • Как создать zip / tgz в Linux, чтобы у Windows были правильные имена файлов?
  • ZIP все файлы в каталоге и загруженные файлы .zip
  • Как создать zip-архив с помощью PowerShell?
  • Можете ли вы настроить Windows на открытие файлов JAR, таких как ZIP-файлы, без стороннего инструмента?
  • Защищенный паролем zip-файл в java
  • Отсутствует опция «Отправить в сжатую папку». Во всяком случае, чтобы восстановить?
  • Есть ли инструмент архива (который работает в Windows), который я могу установить «атрибут выполнения» в архиве или в zip-файле?
  • Ошибка при копировании файлов с символами Unicode в именах с помощью папки «Отправить в сжатую (сжатую) папку Win7»
  • Interesting Posts

    Создайте загрузочный USB-накопитель Linux (Knoppix) (с несколькими разделами) с Linux или Mac OS X

    Fedora 18 сильно перегревается HP Envy 4 1002tx в оболочке Gnome

    Для чего используется <x> .dll?

    Можно ли выполнить строку в MySQL?

    Как использовать grails.plugin.location?

    Как обеспечить отображение формы на «дополнительном» мониторе в сценарии с двумя мониторами?

    C #: Как бы вы создали уникальное имя файла, добавив номер?

    Исправление проблемы библиотеки на E71

    Внедрение no-op std :: ostream

    Что я сделал в своей linux-боксе, неправильно использовал rm

    Не удается войти в Office и OneNote не может подключиться к SkyDrive в Windows 8.1

    Могу ли я решить эту проблему с помощью чистого mysql? (присоединение к ‘;’ разделенные значения в столбце)

    Должен ли я использовать пластиковые / изоляционные шайбы при подключении материнской платы к корпусу?

    Критерии нежелательной почты, используемые Exchange и / или Outlook

    Есть ли такая вещь, как javascript-деминератор (деобфускатор)?

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