Кодирование и декодирование base64 на Java 8
Base64 — схема кодирования, которая позволяет перевести двоичные данные в строку формата ASCII и наоборот. Каждый знак в base64 – это 6 бит двоичных данных. Java 8 дает возможность управлять таким преобразованием.
Base64 используется для предотвращения данных от изменения в процессе передачи посредством информационных систем, таких как электронная почта, которая не может быть 8-битной (они могут исказить 8-битные значения). Например, вы прикрепляете изображение к сообщению электронной почты и хотите, чтобы отправленные и доставленные изображения не отличались. Ваша программа электронной почты в base64 кодирует изображение и вставляет эквивалентный текст в сообщение, как показано ниже:
Content-Disposition: inline; filename=IMG_0006.JPG Content-Transfer-Encoding: base64 /9j/4R/+RXhpZgAATU0AKgAAAAgACgEPAAIAAAAGAAAAhgEQAAIAAAAKAAAAjAESAAMAAAABAAYA AAEaAAUAAAABAAAAlgEbAAUAAAABRRRngEoAAMAAAABAAIAAAExAAIAAAAHAAAApgEyAAIAAAAU AAAArgITAAMAAAABAAEAAIdpAAQAAAABAAAAwgAABCRBcHBsZQBpUGhvbmUgNnMAAAAASAAAAAEA . NOMbnDUk2bGh2yy2yiJcsoBIrvtPe3muBbTRGMdeufmH+Nct4chUXpwSPk/qK9GtJRMWWVFbZ0JH I4rf2dkZSbOjt7hhEzwcujA4I7Gust75pYVwAPpXn+kzNLOVYD7xFegWEKPkHsM/pU1F0NKbNS32 o24sSCOlaaFYLUhjky4x9PSsKL4UJsdWkAz3xirH2dZLy1DM2C44zx1FZqL2PTXY/9k=
Вы можете видеть, что закодированное изображение начинается с / и заканчивается =. Многоточие означает, что весь текст не показан для краткости. Обратите внимание, что такая кодировка будет больше объемом на 33% чем двоичные данные.
Работа с base64 в java
В Java 8 есть base64 интерфейс API. Он состоит из java.util.Base64 классов вместе со своими Encoder и Decoder вложенные static классы. В Base64 представлено несколько static методов для получения кодеров и декодеров:
- Base64.Encoder getEncoder(): Возвращает энкодер для базового варианта.
- Base64.Decoder getDecoder(): Возвращаете декодер для базового варианта.
- Base64.Encoder getMimeEncoder(): Возвращает энкодер для варианта Mime.
- Base64.Encoder getMimeEncoder(int lineLength, byte[] lineSeparator): Возвращает энкодер для модифицированных МИМ вариант с lineLength (с округлением вниз до ближайшего кратного 4 — вывод не разделяется на линии при lineLength
- Base64.Decoder getMimeDecoder(): Возвращает декодер для варианта Mime.
- Base64.Encoder getUrlEncoder(): Возвращает энкодер для URL-адрес и имя безопасный вариант.
- Base64.Decoder getUrlDecoder(): Возвращает декодер для URL-адрес и имя безопасный вариант.
- Base64.Encoder представлено многопоточное выполнение методов экземпляра для кодирования последовательности байтов.
API с помощью base64 на Java прост в использовании. Рассмотрим программу в стиле «Здравствуй, Мир!», которая при помощи base64 кодирует сообщение с помощью базового кодера, а затем осуществляет base64-декодирование. В листинге 1 представлен исходный код:
import java.util.Base64; public class HelloBase64 < public static void main(String[] args) < String msg = "Hello, Base64!"; Base64.Encoder enc = Base64.getEncoder(); byte[] encbytes = enc.encode(msg.getBytes()); for (int i = 0; i < encbytes.length; i++) < System.out.printf("%c", (char) encbytes[i]); if (i != 0 && i % 4 == 0) System.out.print(' '); >System.out.println(); Base64.Decoder dec = Base64.getDecoder(); byte[] decbytes = dec.decode(encbytes); System.out.println(new String(decbytes)); > >
SGVsb G8sI EJhc 2U2N CE= Hello, Base64!
Кодирование и декодирование файлов на Java
base64 более полезно для кодирования файлов. Я создал второе приложение, которое демонстрирует эта полезность наряду с base64 API-интерфейсом. В листинге 2 представлен исходный код приложения.
import java.io.*; import java.util.Base64; public class FileEncDec < public static void main(String[] args) < if (args.length != 1) < System.err.println("Format: java FileEncDec filename"); return; >try (FileInputStream fis = new FileInputStream(args[0])) < Base64.Encoder enc1 = Base64.getEncoder(); Base64.Encoder enc2 = Base64.getMimeEncoder(); Base64.Encoder enc3 = Base64.getUrlEncoder(); OutputStream os1 = enc1.wrap(new FileOutputStream(args[0] + "1.enc")); OutputStream os2 = enc2.wrap(new FileOutputStream(args[0] + "2.enc")); OutputStream os3 = enc3.wrap(new FileOutputStream(args[0] + "3.enc")); int _byte; while ((_byte = fis.read()) != -1) < os1.write(_byte); os2.write(_byte); os3.write(_byte); >os1.close(); os2.close(); os3.close(); > catch (IOException ioe) < System.err.printf("I/O error: %s%n", ioe.getMessage()); >try (FileOutputStream fos1 = new FileOutputStream("1" + args[0]); FileOutputStream fos2 = new FileOutputStream("2" + args[0]); FileOutputStream fos3 = new FileOutputStream("3" + args[0])) < Base64.Decoder dec1 = Base64.getDecoder(); Base64.Decoder dec2 = Base64.getMimeDecoder(); Base64.Decoder dec3 = Base64.getUrlDecoder(); InputStream is1 = dec1.wrap(new FileInputStream(args[0] + "1.enc")); InputStream is2 = dec2.wrap(new FileInputStream(args[0] + "2.enc")); InputStream is3 = dec3.wrap(new FileInputStream(args[0] + "3.enc")); int _byte; while ((_byte = is1.read()) != -1) fos1.write(_byte); while ((_byte = is2.read()) != -1) fos2.write(_byte); while ((_byte = is3.read()) != -1) fos3.write(_byte); is1.close(); is2.close(); is3.close(); >catch (IOException ioe) < System.err.printf("I/O error: %s%n", ioe.getMessage()); >> >
В FileEncDec приложение требует имя файла в качестве одиночного аргумента командной строки.. Каждый байт записывается в другой файл с помощью разных энкодера и выходного потока. Позже, эти файлы открываются и читаются через разные декодеры и входных потоков. Результаты хранятся в трех отдельных файлах.
Запустите полученное приложение следующим образом (предполагается, у вас есть в формате JPEG-файл с именем image.jpg):
java FileEncDec image.jpg
Вы увидите image.jpg1.enc, image.jpg2.enc и image.jpg3.enc файлы в текущем каталоге. В файлах формата .enc текстовое содержимое бинарных файлов. Разница между image.jpg1.enc и image.jpg3.enc в том, что каждый / был заменен _ , и каждый + был заменен на -. Также вы можете наблюдать три файла: 1image.jpg, 2image.jpg и 3image.jpg. Каждый из этих файлов содержит идентичный контент image.jpg.
Интересное в base64
А давайте попробуем в одном из файлов (image.jpg2.enc) заменить всего один символ. Скажем, где-нибудь в середине заменим R на A – один из тысяч символов. Думаете, это что-то изменит? И в нашей программе закомментируем запись в файл image. jpg2.enc, чтобы только прочитало наш закодированный и восстановило по нему картинку. Смотрите сами изменения:

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

Автор этого материала — я — Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML — то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
статьи IT, java, base64, кодирование
кодировка строк в Java
Учу Java . При написании кода потребовалось перекодировать полученную строку. После того, как я прочитал об этом несколько постов и статей — я понял, что в Java строки не имеют понятия кодировки, и, если хочешь ее изменить, то нужно из строки сделать байтовый массив, в массиве поменять кодировку и полученное значение вернуть назад в строку. Получилось что то типа такого:
String data = "Текст который получаю"; data = new String (arr.getBytes("utf8"), "utf8");
- Правильно ли я все понял?
- Правильно ли я реализую это в коде?
Отслеживать
user236980
задан 26 янв 2018 в 2:44
Fariz Mamedow Fariz Mamedow
1,447 2 2 золотых знака 9 9 серебряных знаков 21 21 бронзовый знак
Вы сами ответили на свой вопрос. Есть переменная типа String, соответсвенно, String -обычный класс, который по сути инкапсулирует массив чаров и никакой переменой, хранящей информацию о кодировке там нет, в чем легко убедиться заглянув в сорцы. Поэтому ваши танцы с бубном в виде создания новой переменной типа String ни к чему не приведут. Эта переменная как не хранила инфу о кодировке,так и продолжит ее не хранить, что бы вы не делали.И это правильно, зачем создавать путаницу внутри самой Java.Вопрос кодировки возникнет тогда, когда вы работаете с внешним ресурсом-сайтом,текстовым файлом,бд.
26 янв 2018 в 3:34
@ДмитрийАлександрович да работаю с внешним ресурсом изза этого вопрос. Но не понял верхний код правильно перекодирует или как?
26 янв 2018 в 8:35
Строки не имеют понятия кодировки, поэтому «перекодировать строку» не имеет смысла. Кодировка бывает лишь в момент превращения строки в байты и назад. Расскажите свою настоящую задачу.
26 янв 2018 в 8:45
Если вы конвертируете байты из файла в строку неправильно, ничего не нужно делать со строкой. Просто сконвертируйте правильно.
26 янв 2018 в 8:47
@VladD задача такая что при соеденение с сокетам русские символы превразаются в чефырчку
26 янв 2018 в 8:56
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Кодировка это просто таблица, где каждой букве соответсвует число (помним же, что компьютер хранит только числа?). Поэтому кодировка имеет смысл только в том случае когда массив чисел (byte[], например) нам нужно превратить в строку и нужно понимать с какой буквой ассоциировать каждое число (ну или в обратную сторону).
Таким образом кодировка имеет смысл только при преобразовании в массив байтов или наоборот. Ваша запись в сокет это оно и есть.
Грубо говоря вы прочитали из сокета массив байтов:
byte[] data = socket.read();
Дальше нам нужно этои числа интрпретировать как строку, с правильной таблицей (кодировкой). В этом случае кодировка показывают в какую букву будет преобразовано каждое число:
new String(data, "UTF-8");
И наоборот у нас есть строка, и мы хотим преобразовать её к массиву байтов, мы указываем кодировку, то бишь в какое число будет преобразована каждая буковка:
String data = "abc"; byte[] array = data.getBytes("UTF-8"); socket.write(array);
Если у вас проблемы с русскими буквами — значит скорее всего указали неправильную кодировку. Какую нужно указывать — нужно разбирать что вам собственно приходит из сокета.
Кодирование и декодирование Java Base64
В этом руководстве мы рассмотрим различные утилиты, обеспечивающие функции кодирования и декодирования Base64 в Java.
В основном мы собираемся проиллюстрировать новые API Java 8. Кроме того, мы используем служебные API-интерфейсы Apache Commons.
2. Java 8 для базы 64
Java 8, наконец, добавила возможности Base64 в стандартный API через служебный класс java.util.Base64 .
Давайте начнем с рассмотрения основного процесса кодирования.
2.1. Базовая версия Java 8 Base64
Базовый кодировщик упрощает работу и кодирует ввод как есть, без разделения строк.
Кодер сопоставляет ввод с набором символов в наборе символов A-Za-z0-9+/ . Итак, декодер отбрасывает любые символы вне этого набора.
Давайте сначала закодируем простую строку :
String originalInput = "test input"; String encodedString = Base64.getEncoder().encodeToString(originalInput.getBytes());
Обратите внимание, как мы получаем полный API Encoder с помощью простого служебного метода getEncoder() .
Давайте теперь декодируем эту строку обратно в исходную форму:
byte[] decodedBytes = Base64.getDecoder().decode(encodedString); String decodedString = new String(decodedBytes);
2.2. Кодирование Java 8 Base64 без заполнения
В кодировке Base64 длина закодированной на выходе строки должна быть кратна трем. Кодер добавляет один или два символа заполнения ( = ) в конце вывода по мере необходимости, чтобы выполнить это требование.
После декодирования декодер отбрасывает эти дополнительные символы заполнения. Чтобы глубже изучить отступы в Base64, ознакомьтесь с этим подробным ответом на Stack Overflow .
Иногда нам нужно пропустить заполнение вывода . Например, результирующая строка никогда не будет декодирована обратно. Итак, мы можем просто выбрать кодирование без заполнения :
String encodedString = Base64.getEncoder().withoutPadding().encodeToString(originalInput.getBytes());
2.3. URL-кодирование Java 8
Кодирование URL очень похоже на базовый кодировщик. Кроме того, он использует безопасный алфавит Base64 для URL и имени файла. Кроме того, он не добавляет никакого разделения строк:
String originalUrl = "https://www.google.co.nz/?gfe_rd=cr&ei=dzbFV&gws_rd=ssl#q=java"; String encodedUrl = Base64.getUrlEncoder().encodeToString(originalURL.getBytes());
Декодирование происходит примерно так же. Служебный метод getUrlDecoder() возвращает java.util.Base64.Decoder . Итак, мы используем его для декодирования URL:
byte[] decodedBytes = Base64.getUrlDecoder().decode(encodedUrl); String decodedUrl = new String(decodedBytes);
2.4. MIME-кодирование Java 8
Давайте начнем с создания некоторых основных входных данных MIME для кодирования:
private static StringBuilder getMimeBuffer() StringBuilder buffer = new StringBuilder(); for (int count = 0; count 10; ++count) buffer.append(UUID.randomUUID().toString()); > return buffer; >
Кодер MIME генерирует выходные данные в кодировке Base64, используя базовый алфавит. Однако формат является MIME-дружественным.
Каждая строка вывода не длиннее 76 символов. Кроме того, он заканчивается возвратом каретки, за которым следует перевод строки ( \r\n ):
StringBuilder buffer = getMimeBuffer(); byte[] encodedAsBytes = buffer.toString().getBytes(); String encodedMime = Base64.getMimeEncoder().encodeToString(encodedAsBytes);
В процессе декодирования мы можем использовать метод getMimeDecoder() , который возвращает java.util.Base64.Decoder :
byte[] decodedBytes = Base64.getMimeDecoder().decode(encodedMime); String decodedMime = new String(decodedBytes);
3. Кодирование/декодирование с использованием кода Apache Commons
Во- первых, нам нужно определить зависимость commons-codec в pom.xml :
dependency> groupId>commons-codec/groupId> artifactId>commons-codec/artifactId> version>1.15/version> /dependency>
Основным API является класс org.apache.commons.codec.binary.Base64 . Мы можем инициализировать его с помощью различных конструкторов:
- Base64(boolean urlSafe) создает API Base64, управляя безопасным режимом URL (вкл. или выкл.).
- Base64(int lineLength) создает API Base64 в небезопасном режиме URL и контролирует длину строки (по умолчанию 76).
- Base64(int lineLength, byte[] lineSeparator) создает API Base64, принимая дополнительный разделитель строк, которым по умолчанию является CRLF («\r\n»).
После того, как API Base64 создан, как кодирование, так и декодирование становятся довольно простыми:
String originalInput = "test input"; Base64 base64 = new Base64(); String encodedString = new String(base64.encode(originalInput.getBytes()));
Более того, метод decode() класса Base64 возвращает декодированную строку:
String decodedString = new String(base64.decode(encodedString.getBytes()));
Другой вариант — использовать статический API Base64 вместо создания экземпляра:
String originalInput = "test input"; String encodedString = new String(Base64.encodeBase64(originalInput.getBytes())); String decodedString = new String(Base64.decodeBase64(encodedString.getBytes()));
4. Преобразование строки в массив байтов
Иногда нам нужно преобразовать String в byte[] . Самый простой способ — использовать метод String getBytes() :
String originalInput = "test input"; byte[] result = originalInput.getBytes(); assertEquals(originalInput.length(), result.length);
Мы также можем предоставить кодировку и не зависеть от кодировки по умолчанию. В результате это зависит от системы:
String originalInput = "test input"; byte[] result = originalInput.getBytes(StandardCharsets.UTF_16); assertTrue(originalInput.length() result.length);
Если наша строка закодирована в Base64 , мы можем использовать декодер Base64 :
String originalInput = "dGVzdCBpbnB1dA=="; byte[] result = Base64.getDecoder().decode(originalInput); assertEquals("test input", new String(result));
Мы также можем использовать метод parseBase64Binary () DatatypeConverter :
String originalInput = "dGVzdCBpbnB1dA=="; byte[] result = DatatypeConverter.parseBase64Binary(originalInput); assertEquals("test input", new String(result));
Наконец, мы можем преобразовать шестнадцатеричную строку в byte[] , используя метод DatatypeConverter.parseHexBinary :
String originalInput = "7465737420696E707574"; byte[] result = DatatypeConverter.parseHexBinary(originalInput); assertEquals("test input", new String(result));
5. Вывод
В этой статье объяснялись основы кодирования и декодирования Base64 в Java. Мы использовали новые API, представленные в Java 8 и Apache Commons.
Наконец, есть еще несколько API-интерфейсов, обеспечивающих аналогичную функциональность: java.xml.bind.DataTypeConverter с printHexBinary и parseBase64Binary .
Фрагменты кода можно найти на GitHub .
- 1. Обзор
- 2. Java 8 для базы 64
- 2.1. Базовая версия Java 8 Base64
- 2.2. Кодирование Java 8 Base64 без заполнения
- 2.3. URL-кодирование Java 8
- 2.4. MIME-кодирование Java 8
Кодирование и декодирование Base64 в Java
В этом посте будет обсуждаться кодирование и декодирование Base64 с использованием простой Java, Guava и Apache Commons.
Base64 представляет собой группу подобных схем кодирования двоичного кода в текст, представляющих двоичные данные в формате строки ASCII путем преобразования их в radix-64 представление. Каждый Base64 цифра представляет ровно 6 бит данных, что означает, что 3 байта могут быть представлены 4 6-битными Base64 цифры.
Схемы кодирования Base64 обычно используются, когда необходимо кодировать двоичные данные, которые необходимо хранить и передавать через носители, предназначенные для работы с текстовыми данными. Это необходимо для того, чтобы данные оставались неповрежденными без изменений во время транспортировки. Base64 обычно используется в ряде приложений, включая электронную почту через MIME и хранение сложных данных в XML .
1. Использование Java 8
Java 8, наконец, обеспечила поддержку возможностей кодирования и декодирования Base64, предоставив Base64, Base64.Encoder а также Base64.Decoder класс полезности. Base64 класс состоит из статических методов для получения экземпляров энкодеров ( Base64.Encoder ) и декодеры ( Base64.Decoder ) для схемы кодирования Base64.
В следующей программе используется Base64.Encoder.encodeToString() метод для кодирования указанного массива байтов в кодированную строку Base64 и Base64.Decoder.decode() метод обратного декодирования строки в кодировке Base64 во вновь выделенный массив байтов.
