Кодирование и декодирование 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 <= 0) и lineSeparator.
- 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 - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.