Я использую 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();
Любая помощь будет оценена по достоинству. Я ищу много мест, но не могу найти правильный ответ.
byte[] data = Base64.getDecoder().decode(str);
btoa
сломан и не должен использоваться.
Проблема в том, что байты не являются символами. Кодировка Base64 делает только одну вещь. Он преобразует байты в поток символов, который выдерживает практически любой текстовый транспортный механизм. А декодирование Base64 делает это наоборот, оно преобразует такие символы в байты.
И путаница в том, что вы печатаете эти байты, как если бы они были символами. Они не.
В итоге вы получите одни и те же байты, но javascript и java не согласны с тем, как вы должны превратить это в суррогатную строку, потому что вы пытаетесь вывести ее на консоль. Это ошибка - байты не являются символами. Таким образом, используется какая-то кодировка, а вам это не нужно, потому что эти символы явно не предназначены для такой печати.
Javascript наполовину приравнивает символы и байты и свободно конвертирует один в другой, выбирая случайную кодировку. Уф. Javascript в этом отношении отстой, он такой, какой есть. Документы MDN на btoa
объясняет, почему вы не должны его использовать. Вы столкнулись с проблемой тот.
Не совсем уверен, как вы это исправите в javascript, но, возможно, вам это не нужно. Java отлично декодирует байты, как и javascript, но javascript затем превращает эти байты в символы в какой-то глупой манере, и это вызывает проблему.
Спасибо за Ваш ответ! Вы были абсолютно правы. Проблема, с которой я столкнулся, заключалась в моем желании увидеть печатные символы, которые привели к повреждению данных. В java нет необходимости преобразовывать его в строку, только на последнем этапе обработки.
Для всех, кто заинтересован, способ, которым я решил точную проблему, описанную в моем вопросе, был следующим: 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();
То, что у вас есть, это вовсе не текстовая строка. Раздача - это АА в начале. Те сопоставляются с количеством нулевых байтов. Это не преобразуется в осмысленный текст ни в одном стандартном наборе символов.
Так что у вас там скорее всего бинарные данные. Преобразование его в строку не даст вам значимого текста.
Теперь, чтобы объяснить разницу, которую вы видите между Java и Javascript. Мне кажется, что и Java, и Javascript прилагают «максимальные усилия» для преобразования двоичных данных, как если бы они были закодированы в ISO-8859-1 (он же ISO LATIN-1).
Проблема в том, что некоторые байтовые коды сопоставляются с неназначенными кодами.
?
либо при создании строки, либо при ее выводе.Для справки, вот как для меня работает онлайн-декодер base64:
����������������Æû$SF3«àöBâ
Неназначенные коды: 0x91, 0x82 и 0x93. 0x15 и 0x0B — непечатаемые управляющие коды.
Но суть в том, что вы не должны преобразовывать эти данные в строку ни в Java, ни в Javascript. Его следует рассматривать как двоичный; то есть массив байтовых значений.
Похоже, вам нужно выбрать кодировку строки. Или, точнее, вам может понадобиться даже не строка, а байт[].