Рубрики
Без рубрики

Кодирование и декодирование строк Base64 в Java

В этом уроке мы будем кодировать и декодировать строки Base64 на Java с примерами. Мы также выполним кодировку Base64 с помощью Apache Commons.

Автор оригинала: David Landup.

Вступление

Процесс преобразования данных путем применения некоторых методов/правил в новый формат называется кодированием . Декодированием является обратным процессом кодирования – возвращением закодированных данных в исходный формат.

Кодирование окружает нас повсюду, и компьютеры в значительной степени полагаются на различные форматы кодирования для доставки и передачи информации.

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

Кодирование гарантирует, что данные останутся нетронутыми и эффективными для транспортировки.

Что такое Base64?

Base64 -это схема кодирования двоичного кода в текст. Он представлен в виде печатаемых символов ASCII, где каждый символ Base64 содержит 6 бит двоичной информации.

Это очень полезно для хранения графической/аудиоинформации в виде строк информации. То, чем Base64 не является , является алгоритмом шифрования.

Хотя это в какой-то степени “скрывает” данные, это ни в коем случае не безопасный формат.

Как Работает Base64?

В Base64, как следует из названия, для кодирования двоичных данных используется 64 символа. Эти персонажи являются:

  • 26 Заглавных букв [A-Z]
  • 26 нижних букв [a-z]
  • 10 цифр [0-9]
  • 2 специальных символа [+ ,/]

Примечание: Существует также 65-й символ ( = ) , который имеет особое значение и называется дополняющим символом .

Как обычно, когда речь заходит о компьютерах, числа представлены в степени 2. Таким образом, 64 символа Base64 могут быть записаны как: $$ ^6 $$ Каждый символ представлен в 6 битах. Вы могли бы подняться выше этого и сделать так, чтобы каждый символ представлял 8 бит. Это будет база 256. Однако это непрактично из-за трудностей в процессе кодирования/декодирования.

Давайте продолжим и вручную закодируем простую строку, чтобы получить хорошее представление о том, как работает этот процесс.

Кодирование вручную

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

  1. Возьмите значения ASCII входных символов отдельно:
Характер A B C 1 2 3
ASCII (десятичный) 65 66 67 49 50 51
  1. Преобразуйте десятичное значение каждого символа в 8-разрядный двоичный код:
Характер A B C 1 2 3
ASCII 65 66 67 49 50 51
Двоичный 01000001 01000010 01000011 110001 110010 110011
  1. Переупорядочьте двоичные числа в блоки по 6 бит:

    010000 010100 001001 000011 001100 010011 001000 110011

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

  2. Получите десятичные значения этих двоичных фрагментов:

Двоичный 10000 10100 1001 11 1100 10011 1000 110011
Десятичный 16 20 9 3 12 19 8 51
  1. Наконец, используя диаграмму Base64, преобразуйте каждое десятичное число в символ Base64:
Ценность Обуглить Ценность Обуглить Ценность Обуглить Ценность Обуглить
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /

В конце концов, у нас остается строка QUJDMTIz – представление Base64 ABC123 .

Примечание: 6 входных символов в конце кодируются в 8 символов. Это означает, что для хранения строки в кодировке Base64 требуется на ~33% больше места, чем для исходной строки.

Зачем использовать кодировку Base64?

Компьютеры работают с 0 s и 1 s, так зачем беспокоиться о преобразовании этого в другой формат?

Да, это правда. Двоичный является языком компьютеров. Вот именно поэтому мы его преобразуем. Последовательность, такая как 0010110 это может означать многое. Это может быть часть изображения, это может быть часть аудиофайла или это может быть команда, которая удаляет половину вашего жесткого диска.

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

Кодирование строк с помощью Java 8 – Base64

Java 8 познакомила нас с новым классом – Base64 . Он поддерживает кодирование и декодирование нескольких типов вариантов данных, указанных в RFC 2045 и RFC 4648 :

  • Основной
  • Безопасный URL и имя файла
  • МИМ

Базовое кодирование и декодирование строк

Используя базовый кодер, мы можем закодировать строку в Base64. Базовый кодировщик не добавляет символ разделителя строк.

Если длина строки не делится на 3 (8-разрядное представление не сможет объединяться в 6-разрядные группы), в конце будет добавлено дополнение в виде = :

Encoder encoder = Base64.getEncoder();
String originalString = "basic";
String encodedString = encoder.encodeToString(originalString.getBytes());

System.out.println(encodedString);

Base64 – это заводской класс, из которого мы будем извлекать различные реализации/варианты кодера. Метод encodeToString() закодирует ваши входные данные в представление входных данных Base64 и упакует их в строку. Вы также можете использовать метод encode() для кодирования его в байт поток или байтбуфер вместо этого.

При необходимости вы также можете вернуть экземпляр кодировщика, который не будет заполнять входные строки с помощью метода без заполнения() при создании экземпляра из заводского класса:

Base64.getEncoder().withoutPadding();

Примечание: Кодирование без заполнения, скорее всего, приведет к строке Base64, которая не может быть декодирована обратно, так как часть информации потеряна.

Выполнение примера кода приведет к:

YmFzaWM=

С нашей закодированной строкой давайте также создадим экземпляр Декодера и декодируем полученную строку. Однако декодеры работают только с массивами байт :

Decoder decoder = Base64.getDecoder();
byte[] bytes = decoder.decode(encodedString);
		
System.out.println(new String(bytes));

Этот код приведет к:

basic

Кодирование и декодирование URL-адресов

Для кодирования и декодирования URL-адресов мы можем использовать экземпляр Кодера и Декодера , которые используют безопасный тип URL и имени файла Base64. Они также не добавляют символ разделителя строк.

Мы получаем их с помощью методов getUrlEncoder() и getUrlDecoder() через Base64 завод:

Encoder encoder = Base64.getUrlEncoder();
String originalinput = "https://stackabuse.com/tag/java/";
String encodedUrl = encoder.encodeToString(originalinput.getBytes());

System.out.println(encodedUrl);

Как и раньше, метод encodeToString() будет кодировать входные данные и упаковывать их в строку:

aHR0cHM6Ly9zdGFja2FidXNlLmNvbS90YWcvamF2YS8=

Метод encode() будет кодировать входные данные в массив байт . Опять же, метод decode() работает с массивом байт и декодирует строку Base64 в исходную:

Decoder decoder = Base64.getUrlDecoder();
byte[] bytes = decoder.decode(encodedUrl);

System.out.println(new String(bytes));

Выполнение этого кода дает:

https://stackabuse.com/tag/java/

Примечание : В этой схеме доступны три специальных символа: + , / , = . Эти символы могут иметь другое значение в URL-адресах и некоторых файловых системах и могут вызвать проблему, если используется закодированная строка. Чтобы избежать этих проблем, строки URL и файлов должны быть закодированы и декодированы с помощью безопасного для URL декодера.

Символы + и / заменяются на - и _ соответственно.

Кодирование и декодирование MIME

Универсальное расширение интернет-почты (MIME) метки используются для идентификации типа носителя (HTML, аудио, видео).

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

При отправке вложений, таких как файл .txt , они кодируются в Base64 и прикрепляются к электронному письму. Вот как может выглядеть вложение:

Content-Type: text/plain;
name="log_attachment.txt"
Content-Disposition: attachment;
filename="attachment.txt"
Content-Transfer-Encoding: base64

TUlNRS1WZXJzaW9uOiAxLjANClgtTWFpbGVyOiBNYWlsQmVlLk5FVCA4LjAuNC40MjgNClN1Ympl
Y3Q6IHRlc3Qgc3ViamVjdA0KVG86IGtldmlubUBkYXRhbW90aW9uLmNvbQ0KQ29udGVudC1UeXBl
OiBtdWx0aXBhcnQvYWx0ZXJuYXRpdmU7DQoJYm91bmRhcnk9Ii0tLS09X05leHRQYXJ0XzAwMF9B
RTZCXzcyNUUwOUFGLjg4QjdGOTM0Ig0KDQoNCi0tLS0tLT1fTmV4dFBhcnRfMDAwX0FFNkJfNzI1
RTA5QUYuODhCN0Y5MzQNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsNCgljaGFyc2V0PSJ1dGYt
OCINCkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IHF1b3RlZC1wcmludGFibGUNCg0KdGVzdCBi
b2R5DQotLS0tLS09X05leHRQYXJ0XzAwMF9BRTZCXzcyNUUwOUFGLjg4QjdGOTM0DQpDb250ZW50
LVR5cGU6IHRleHQvaHRtbDsNCgljaGFyc2V0PSJ1dGYtOCINCkNvbnRlbnQtVHJhbnNmZXItRW5j
b2Rpbmc6IHF1b3RlZC1wcmludGFibGUNCg0KPHByZT50ZXN0IGJvZHk8L3ByZT4NCi0tLS0tLT1f
TmV4dFBhcnRfMDAwX0FFNkJfNzI1RTA5QUYuODhCN0Y5MzQtLQ0K

При кодировании MIME выходные данные форматируются так, чтобы они были удобными для MIME-строки не могут содержать более 76 символов , и каждая строка заканчивается на \r\n , естественно, за исключением последней. \r является символом возврата каретки, в то время как \n является символом новой строки.

Давайте создадим файл под названием file.txt который содержит:

"I met a traveller from an antique land,
Who said - "Two vast and trunkless legs of stone
Stand in the desert.... Near them, on the sand,
Half sunk a shattered visage lies, whose frown,
And wrinkled lip, and sneer of cold command,
Tell that its sculptor well those passions read
Which yet survive, stamped on these lifeless things,
The hand that mocked them, and the heart that fed;
And on the pedestal, these words appear:
My name is Ozymandias, King of Kings;
Look on my Works, ye Mighty, and despair!
Nothing beside remains. Round the decay
Of that colossal Wreck, boundless and bare
The lone and level sands stretch far away."

Ozymandias, by Percy Bysshe Shelley

Теперь давайте прочитаем байты файла и упакуем их в массив байт , после чего мы его закодируем:

byte[] bytes = Files.readAllBytes(Paths.get("path/to/file"));
String encodedString = Base64.getMimeEncoder().encodeToString(bytes);
System.out.println(encodedString);

Git Essentials

Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!

Этот код даст нам:

IkkgbWV0IGEgdHJhdmVsbGVyIGZyb20gYW4gYW50aXF1ZSBsYW5kLA0KV2hvIHNhaWTigJTigJxU
d28gdmFzdCBhbmQgdHJ1bmtsZXNzIGxlZ3Mgb2Ygc3RvbmUNClN0YW5kIGluIHRoZSBkZXNlcnQu
Li4uIE5lYXIgdGhlbSwgb24gdGhlIHNhbmQsDQpIYWxmIHN1bmsgYSBzaGF0dGVyZWQgdmlzYWdl
IGxpZXMsIHdob3NlIGZyb3duLA0KQW5kIHdyaW5rbGVkIGxpcCwgYW5kIHNuZWVyIG9mIGNvbGQg
Y29tbWFuZCwNClRlbGwgdGhhdCBpdHMgc2N1bHB0b3Igd2VsbCB0aG9zZSBwYXNzaW9ucyByZWFk
DQpXaGljaCB5ZXQgc3Vydml2ZSwgc3RhbXBlZCBvbiB0aGVzZSBsaWZlbGVzcyB0aGluZ3MsDQpU
aGUgaGFuZCB0aGF0IG1vY2tlZCB0aGVtLCBhbmQgdGhlIGhlYXJ0IHRoYXQgZmVkOw0KQW5kIG9u
IHRoZSBwZWRlc3RhbCwgdGhlc2Ugd29yZHMgYXBwZWFyOg0KTXkgbmFtZSBpcyBPenltYW5kaWFz
LCBLaW5nIG9mIEtpbmdzOw0KTG9vayBvbiBteSBXb3JrcywgeWUgTWlnaHR5LCBhbmQgZGVzcGFp
ciENCk5vdGhpbmcgYmVzaWRlIHJlbWFpbnMuIFJvdW5kIHRoZSBkZWNheQ0KT2YgdGhhdCBjb2xv
c3NhbCBXcmVjaywgYm91bmRsZXNzIGFuZCBiYXJlDQpUaGUgbG9uZSBhbmQgbGV2ZWwgc2FuZHMg
c3RyZXRjaCBmYXIgYXdheS7igJ0NCg0KT3p5bWFuZGlhcywgYnkgUGVyY3kgQnlzc2hlIFNoZWxs
ZXk=

Естественно, расшифровать этот контент так же просто, как:

Decoder decoder = Base64.getMimeDecoder();
byte[] decodedBytes = decoder.decode(encodedString);
System.out.println(new String(decodedBytes));

Этот код даст:

"I met a traveller from an antique land,
Who said - "Two vast and trunkless legs of stone
Stand in the desert.... Near them, on the sand,
Half sunk a shattered visage lies, whose frown,
And wrinkled lip, and sneer of cold command,
Tell that its sculptor well those passions read
Which yet survive, stamped on these lifeless things,
The hand that mocked them, and the heart that fed;
And on the pedestal, these words appear:
My name is Ozymandias, King of Kings;
Look on my Works, ye Mighty, and despair!
Nothing beside remains. Round the decay
Of that colossal Wreck, boundless and bare
The lone and level sands stretch far away."

Ozymandias, by Percy Bysshe Shelley

Apache Commons

Из-за его полезности и распространенности в Java многие проекты включают Apache Commons в путь к классам. Это отличная библиотека со множеством полезных функций, часто используемых в производстве, и кодирование/декодирование не является исключением.

Используя Maven, добавить его в свой проект так же просто, как включить зависимость:


    commons-codec
    commons-codec
    ${version}

Или, если вы используете Gradle:

compile group: 'commons-codec', name: 'commons-codec', version: '${version}'

Как и в официальной реализации Java, класс Base64 является основным API. Хотя вместо того, чтобы использоваться в качестве фабрики для экземпляров Encoder /| Decoder , сам класс обрабатывает все кодирование и декодирование. Другими полезными методами, которые он предоставляет, являются такие методы, как isBase64 () , isInAlphabet() и isUrlSafe() .

Базовое кодирование и декодирование строк Apache Commons

Давайте продолжим и закодируем простую строку в Base64. Метод encodeBase64() принимает массив байт и возвращает массив байт , представляющий закодированный ввод.

String inputString = "Some String";
byte[] bytes = Base64.encodeBase64(inputString.getBytes());

System.out.println(new String(bytes));

Запуск этого кода приведет к:

U29tZSBTdHJpbmc=

В качестве альтернативы вы можете использовать метод encodeBase64String () , который вернет строку вместо массива байт :

String inputString = "Some String";
String encodedString = Base64.encodeBase64String(inputString.getBytes());

System.out.println(encodedString);

Запуск этого кода приведет к:

U29tZSBTdHJpbmc=

В том же духе класс Base64 также используется в качестве декодера. Он принимает байт массив или строку и возвращает байт массив:

String decodedString = new String(Base64.decodeBase64(encodedString.getBytes()));
System.out.println(decodedString);
// Or
String anotherDecodedString = new String(Base64.decodeBase64(encodedString));
System.out.println(anotherDecodedString);

Запуск этого кода приведет к:

Some String
Some String

Кодирование и декодирование URL-адресов Apache Commons

Кодирование и декодирование URL-адресов выполняется по тому же принципу:

String originalInput = "https://stackabuse.com/tag/java/";
byte[] bytes = Base64.encodeBase64URLSafe(originalInput.getBytes());

System.out.println(new String(bytes));

Выполнение этого приведет к:

aHR0cHM6Ly9zdGFja2FidXNlLmNvbS90YWcvamF2YS8=

Вы также можете вернуть строку вместо байта массива:

String originalInput = "https://stackabuse.com/tag/java/";
String encodedString = Base64.encodeBase64URLSafeString(originalInput.getBytes());

System.out.println(encodedString);

Содержимое кодированной строки является:

aHR0cHM6Ly9zdGFja2FidXNlLmNvbS90YWcvamF2YS8=

И, наконец, мы также можем декодировать представление URL-адреса Base64:

String decodedUrl = new String(Base64.decodeBase64(encodedString.getBytes()));
System.out.println(decodedUrl);
// Or
String anotherDecodedUrl = Base64.decodeBase64(encodedString);
System.out.println(anotherDecodedUrl);
https://stackabuse.com/tag/java/
https://stackabuse.com/tag/java/

Кодирование и декодирование MIME в Apache Commons

Кодирование и декодирование типов MIME немного отличается от официальной реализации Java. На этот раз мы используем метод encodeBase64Chunked() :

byte[] bytes = Files.readAllBytes(Paths.get("path/to/file"));
String encodedString = new String(Base64.encodeBase64Chunked(bytes));
System.out.println(encodedString);

Этот код приводит к:

IkkgbWV0IGEgdHJhdmVsbGVyIGZyb20gYW4gYW50aXF1ZSBsYW5kLA0KV2hvIHNhaWTigJTigJxU
d28gdmFzdCBhbmQgdHJ1bmtsZXNzIGxlZ3Mgb2Ygc3RvbmUNClN0YW5kIGluIHRoZSBkZXNlcnQu
Li4uIE5lYXIgdGhlbSwgb24gdGhlIHNhbmQsDQpIYWxmIHN1bmsgYSBzaGF0dGVyZWQgdmlzYWdl
IGxpZXMsIHdob3NlIGZyb3duLA0KQW5kIHdyaW5rbGVkIGxpcCwgYW5kIHNuZWVyIG9mIGNvbGQg
Y29tbWFuZCwNClRlbGwgdGhhdCBpdHMgc2N1bHB0b3Igd2VsbCB0aG9zZSBwYXNzaW9ucyByZWFk
DQpXaGljaCB5ZXQgc3Vydml2ZSwgc3RhbXBlZCBvbiB0aGVzZSBsaWZlbGVzcyB0aGluZ3MsDQpU
aGUgaGFuZCB0aGF0IG1vY2tlZCB0aGVtLCBhbmQgdGhlIGhlYXJ0IHRoYXQgZmVkOw0KQW5kIG9u
IHRoZSBwZWRlc3RhbCwgdGhlc2Ugd29yZHMgYXBwZWFyOg0KTXkgbmFtZSBpcyBPenltYW5kaWFz
LCBLaW5nIG9mIEtpbmdzOw0KTG9vayBvbiBteSBXb3JrcywgeWUgTWlnaHR5LCBhbmQgZGVzcGFp
ciENCk5vdGhpbmcgYmVzaWRlIHJlbWFpbnMuIFJvdW5kIHRoZSBkZWNheQ0KT2YgdGhhdCBjb2xv
c3NhbCBXcmVjaywgYm91bmRsZXNzIGFuZCBiYXJlDQpUaGUgbG9uZSBhbmQgbGV2ZWwgc2FuZHMg
c3RyZXRjaCBmYXIgYXdheS7igJ0NCg0KT3p5bWFuZGlhcywgYnkgUGVyY3kgQnlzc2hlIFNoZWxs
ZXk=

Расшифровка такая же, как и раньше:

String decodedMime = new String(Base64.decodeBase64(encodedString.getBytes()));
System.out.println(decodedMime);
// Or
String anotherDecodedMime = Base64.decodeBase64(encodedString);
System.out.println(anotherDecodedMime);

Этот код приводит к:

"I met a traveller from an antique land,
Who said - "Two vast and trunkless legs of stone
Stand in the desert.... Near them, on the sand,
Half sunk a shattered visage lies, whose frown,
And wrinkled lip, and sneer of cold command,
Tell that its sculptor well those passions read
Which yet survive, stamped on these lifeless things,
The hand that mocked them, and the heart that fed;
And on the pedestal, these words appear:
My name is Ozymandias, King of Kings;
Look on my Works, ye Mighty, and despair!
Nothing beside remains. Round the decay
Of that colossal Wreck, boundless and bare
The lone and level sands stretch far away."

Ozymandias, by Percy Bysshe Shelley

Вспомогательные методы Apache Commons

В истинной манере Apache Commons мы познакомились с несколькими вспомогательными методами, которые немного облегчают нашу жизнь. Например, мы можем проверить, находится ли строка или массив байт в допустимой базе 64:

String originalInput = "https://stackabuse.com/tag/java/";
byte[] bytes = Base64.encodeBase64URLSafe(originalInput.getBytes());

System.out.println(Base64.isBase64(bytes));
// Or
System.out.println(Base64.isBase64(encodedString));

Этот код приведет к:

true 
true

Мы можем проверить, находимся ли мы в безопасном для URL режиме или нет:

System.out.println(Base64.isUrlSafe());

Поскольку мы закодировали строку URL-адреса с помощью метода encodeBase64URLSafe () , этот код приводит к:

true

И, наконец, мы можем проверить, соответствует ли каждый отдельный байт из нашего массива алфавиту Base64:

for (int i = 0; i < bytes.length; i++) {
    System.out.println(Base64.isInAlphabet(bytes[i]));
}

Вывод

В этой статье мы углубились в то, что такое кодирование и декодирование, а затем в обзор Base64. Мы вручную закодировали строку, чтобы лучше понять процесс, перед многими примерами кода.

Использование класса Base64 в Java позволяет нам создавать различные типы кодеров и декодеров, оптимизированных для кодирования и декодирования базовых строк, URL – адресов и типов MIME.

Используя класс Base64 , предоставленный Apache Commons, мы полагаемся на базовый класс для непосредственного кодирования.