Кодирование и декодирование 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 - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Программы на заказ
Отзывы
Контакты