Кодирование и декодирование 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 представлено многопоточное выполнение методов экземпляра для кодирования последовательности байтов.
Hello, Base64

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):

base64 на Java 8

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, чтобы только прочитало наш закодированный и восстановило по нему картинку. Смотрите сами изменения:

base64 ошибочный

Есть отличие, не правда ли? Теперь вы понимаете, почему в начале статьи я написал о важности передачи без искажений? Если у вас есть вопросы по статье или необходимо написать программу на Java, То вы можете обратиться ко мне – за небольшую плату я вам с удовольствием помогу.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегистатьи IT, java, base64, кодирование




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




Урок 33. Вспомогательная функция JavaScript
Лихо закрученный триллер
Визуальный редактор и простой файловый менеджер Laravel 9