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

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

Вступление

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

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

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

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

Что такое Base64?

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

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

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

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

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

  • 26 заглавных букв [AZ]
  • 26 строчных букв [az]
  • 10 цифр [0–9]
  • 2 специальных символа [+, /]

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

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

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

Ручное кодирование

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

  1. Отдельно возьмем значения ASCII входных символов:

Персонаж А B C 1 2 3 ASCII (десятичный) 65 66 67 49 50 51


  1. Преобразуйте десятичное значение каждого символа в 8-битное двоичное:

Персонаж А B C 1 2 3 ASCII 65 66 67 49 50 51 Двоичный 01000001 01000010 01000011 00110001 00110010 00110011


  1. Измените порядок двоичных чисел на блоки по 6 бит:

    010000 010100 001001 000011 001100 010011 001000 110011

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

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


Двоичный 010000 010100 001001 000011 001100 010011 001000 110011 Десятичный 16 20 9 3 12 19 8 51


  1. Наконец, используя диаграмму Base64, преобразуйте каждое десятичное число в символ Base64:

Значение Char Значение Char Значение Char Значение Char 0 А 16 Q 32 грамм 48 ш 1 B 17 р 33 час 49 Икс 2 C 18 S 34 я 50 y 3 D 19 Т 35 год j 51 z 4 E 20 U 36 k 52 0 5 F 21 год V 37 л 53 1 6 грамм 22 W 38 м 54 2 7 ЧАС 23 Икс 39 п 55 3 8 я 24 Y 40 о 56 4 9 J 25 Z 41 год п 57 5 10 K 26 а 42 q 58 6 11 L 27 б 43 год р 59 7 12 M 28 год c 44 год s 60 8 13 N 29 d 45 т 61 9 14 О 30 е 46 ты 62 + 15 п 31 год ж 47 v 63 /


В конце концов, у нас осталась строка QUJDMTIz - представление ABC123 в формате Base64.

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

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

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

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

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

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

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

  • Базовый
  • URL и имя файла безопасны
  • MIME

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

Используя базовый кодировщик, мы можем закодировать строку в 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() чтобы вместо этого кодировать его в поток byte ByteBuffer

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

 Base64.getEncoder().withoutPadding(); 

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

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

 YmFzaWM= 

Закодировав нашу строку, давайте также создадим экземпляр Decoder и декодируем созданную строку. Но декодеры работают только с byte массивами:

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

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

 basic 

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

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

Мы получаем их с помощью 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() кодирует ввод в массив byte Опять же, метод decode() работает с byte массивом и декодирует строку 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 массив, после чего мы его закодируем:

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

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

 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, добавить его в свой проект так же просто, как включить зависимость:

 <dependency> 
 <groupId>commons-codec</groupId> 
 <artifactId>commons-codec</artifactId> 
 <version>${version}</version> 
 </dependency> 

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

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

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

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

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

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

Запуск этого кода даст:

 U29tZSBTdHJpbmc= 

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

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

Запуск этого кода даст:

 U29tZSBTdHJpbmc= 

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

 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 вместо массива byte

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

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 мы познакомились с несколькими вспомогательными методами, которые сделают нашу жизнь немного проще. Например, мы можем проверить, находится ли строка или byte в допустимом Base64:

 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 

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

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

Заключение

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

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

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

comments powered by Disqus