2016-10-05 10 views
0

Каков наилучший способ преобразования произвольной строки Java в ограниченный набор символов и обратно?Как преобразовать произвольную строку Java в ограниченный набор символов обратимым образом?

Я хотел бы сгенерировать ETag из произвольной строки Java и затем воспроизвести исходную строку, когда будет представлен этот ETag.

RFC 7232 и RFC 7230 между ними определяют допустимые символы как:

etagc   = %x21/%x23-7E/obs-text 
       ; VCHAR except double quotes, plus obs-text 
obs-text  = %x80-FF 

затягивая, это означает, что любой 8 бит символов больше или равно 0x21, за исключением 0x22 и 0x7f. Учитывая, что строки Java могут содержать любой символ Юникода, существует немало, которые недопустимы в ETag.

Упрощенно, потому что 0 - 9 и A - F все допустимые символы Etag, я мог бы:

  1. преобразовать строку в массив байтов UTF-8;
  2. затем преобразуйте каждый байт в двухзначный шестнадцатеричный номер;
  3. затем объедините шестнадцатеричные числа, чтобы сделать ETag.

Код для реверса это немного больно, но это является совершенно обратимым, и это работает для всех Java Strings.

Однако мой упрощенный метод производит очень длинные ETags, что является неэффективным и может вызвать проблемы на практике.

Как я могу изготовить более короткие ETags, используя тот факт, что для меня есть 220 символов? Есть ли библиотека для этой цели?

+4

Вы ищете Base64. – SLaks

+0

Base64. Поищи это. –

+0

Ну ... Я ищу Base220 –

ответ

0

Я не думаю, что есть библиотека для кодирования/декодирования «base 220», которая соответствует вашей спецификации. (Хотя, возможно, вы захотите взглянуть на Furcadia Base 220 Encoding для кодирования блоков фиксированной длины.) Вы можете сделать лучше, чем Base 64 с базой 91 (см. here и обновленную версию на Github).

Если вы хотите использовать как можно больше из 220 символов, вам придется сворачивать самостоятельно. Коды Base 64 или Base 91 являются хорошими отправными точками. (Особенно анализ различий между ними даст вам представление о том, как добраться до 220.) Поскольку вам приходится иметь дело с произвольной длиной ввода, вы не должны ожидать, что сможете в полной мере использовать 220 символов для кодированных данных. Вам нужно будет зарезервировать некоторые символы для управления сигналами, заполнения и т. Д. Или ввести дополнительные данные в закодированный поток, чтобы указать длину строки.

0

Если ваши строки в основном ASCII, реализовать модифицированныйUTF-8(вариант, но не следует путать с, MUTF-8), где модификация является то, что 0x00 - 0x20, 0x22 и 0x7f все закодировано в 2 байта.

Это хорошо работает, потому что многобайтовые последовательности UTF-8 используют только 0x80 - 0xff, которые все действуют в ETag, в соответствии со спецификацией, на которую вы ссылались.

Пример: Строка Java "Test \"\u20AC\"", что текст Test "€", будет кодировать в байтах 54 65 73 74 c0 81 c2 81 e2 82 ac c2 81, который будет отображаться в ISO-8859-1 в TestÀÂâ¬Â и в Windows-1252, как TestÀ�Â�€Â�.


Однако, используя байты 0x80 - 0xff в HTTP заголовках может вызвать проблемы (например, см текстовое отображение байтов 81 и 82 выше), так что лучше, чтобы избежать их, если это возможно.

Это возможно, если вы используете только стандартную кодировку Base64. Вы, конечно, сначала должны будете закодировать свой текст в байтах. Если ваши строки в основном ASCII, используйте UTF-8, иначе просто используйте значения 2 байта char, т. Е. Используйте UTF-16.

Пример: Используя ту же самую Java-строку, что и выше, она будет кодироваться до VGVzdCAi4oKsIg==, которая состоит из чистых действительных символов ASCII.

В Java 8, что это легко сделать:

String input = "Test \"\u20AC\""; // 20AC is Euro sign 
byte[] utf8Bytes = input.getBytes(StandardCharsets.UTF_8); 
String base64Encoded = Base64.getEncoder().encodeToString(utf8Bytes);