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

Я использую Java, и у меня есть строка в кодировке Base64, которую я хочу декодировать, а затем выполнить некоторые операции для преобразования.

Правильное декодированное значение получается в JavaScript через функцию atob(), но в java с помощью Base64.decodeBase64() я не могу получить равное значение.

Пример:

За:

String str = "AAAAAAAAAAAAAAAAAAAAAMaR+ySCU0Yzq+AV9pNCCOI = "

С JavaScript atob(str) я получаю ->

"Æ‘û$‚SF3«àö“Bâ"

С Java new String(Base64.decodeBase64(str)) я получаю ->

"Æ?û$?SF3«à§ö?â"


Еще один способ решить эту проблему — запустить JavaScript на Java с движком Nashorn, но я получаю сообщение об ошибке рядом с символом "$".

Текущий код:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
String script2 = "function decoMemo(memoStr){ print(atob(memoStr).split('')" + 
    ".map((aChar) => `0${aChar.charCodeAt(0).toString(16)}`" +
    ".slice(-2)).join('').toUpperCase());}";
try {
    engine.eval(script2);
    Invocable inv = (Invocable) engine;
    String returnValue = (String)inv.invokeFunction("decoMemo", memoTest );
    System.out.print("\n result: " + returnValue);
} catch (ScriptException | NoSuchMethodException e1) {
    e1.printStackTrace();

Любая помощь будет оценена по достоинству. Я ищу много мест, но не могу найти правильный ответ.

Похоже, вам нужно выбрать кодировку строки. Или, точнее, вам может понадобиться даже не строка, а байт[].

Louis Wasserman 07.05.2022 02:10
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
49
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

byte[] data = Base64.getDecoder().decode(str);
Ответ принят как подходящий

btoa сломан и не должен использоваться.

Проблема в том, что байты не являются символами. Кодировка Base64 делает только одну вещь. Он преобразует байты в поток символов, который выдерживает практически любой текстовый транспортный механизм. А декодирование Base64 делает это наоборот, оно преобразует такие символы в байты.

И путаница в том, что вы печатаете эти байты, как если бы они были символами. Они не.

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

Javascript наполовину приравнивает символы и байты и свободно конвертирует один в другой, выбирая случайную кодировку. Уф. Javascript в этом отношении отстой, он такой, какой есть. Документы MDN на btoa объясняет, почему вы не должны его использовать. Вы столкнулись с проблемой тот.

Не совсем уверен, как вы это исправите в javascript, но, возможно, вам это не нужно. Java отлично декодирует байты, как и javascript, но javascript затем превращает эти байты в символы в какой-то глупой манере, и это вызывает проблему.

Спасибо за Ваш ответ! Вы были абсолютно правы. Проблема, с которой я столкнулся, заключалась в моем желании увидеть печатные символы, которые привели к повреждению данных. В java нет необходимости преобразовывать его в строку, только на последнем этапе обработки.

José Braga 11.05.2022 00:04

Для всех, кто заинтересован, способ, которым я решил точную проблему, описанную в моем вопросе, был следующим: byte[] decodedByteArray = Base64.decodeBase64(encyptedString); StringBuilder sb = new StringBuilder(); for (byte b : decodedByteArray) { sb.append(String.format("%02X ", b)); } System.out.println("Hexadecimal String: " + sb.toString()); String decodedStr = sb.toString().replace(" ","").toUpperCase();

José Braga 11.05.2022 00:11

То, что у вас есть, это вовсе не текстовая строка. Раздача - это АА в начале. Те сопоставляются с количеством нулевых байтов. Это не преобразуется в осмысленный текст ни в одном стандартном наборе символов.

Так что у вас там скорее всего бинарные данные. Преобразование его в строку не даст вам значимого текста.


Теперь, чтобы объяснить разницу, которую вы видите между Java и Javascript. Мне кажется, что и Java, и Javascript прилагают «максимальные усилия» для преобразования двоичных данных, как если бы они были закодированы в ISO-8859-1 (он же ISO LATIN-1).

Проблема в том, что некоторые байтовые коды сопоставляются с неназначенными кодами.

  • В случае Java эти неназначенные коды сопоставляются с ? либо при создании строки, либо при ее выводе.
  • В случае Javascript неназначенные коды либо не включаются в строку, либо удаляются при попытке их отображения.

Для справки, вот как для меня работает онлайн-декодер base64:

  ����������������Æû$SF3«àöBâ

Неназначенные коды: 0x91, 0x82 и 0x93. 0x15 и 0x0B — непечатаемые управляющие коды.


Но суть в том, что вы не должны преобразовывать эти данные в строку ни в Java, ни в Javascript. Его следует рассматривать как двоичный; то есть массив байтовых значений.

Другие вопросы по теме