Что это за символы, которые приводят к сбою URLDecoder с UTF-8?

Я использую URLDecoder для декодирования строки:

import java.net.URLDecoder;
URLDecoder.decode("%u6EDA%u52A8%u8F74%u627F", StandardCharsets.UTF_8.name());

Что приводит к краху

Exception in thread "main" java.lang.IllegalArgumentException: URLDecoder: Illegal hex characters in escape (%) pattern - For input string: "u6"
    at java.net.URLDecoder.decode(URLDecoder.java:194)
    at Playground$.delayedEndpoint$Playground$1(Playground.scala:45)
    at Playground$delayedInit$body.apply(Playground.scala:10)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:392)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
    at scala.App$class.main(App.scala:76)
    at Playground$.main(Playground.scala:10)
    at Playground.main(Playground.scala)

Кажется, что %u6 и %u8 не разрешены в строке. Я пытался прочитать, что это за символы, но безуспешно. Я нашел строку в наборе данных в поле под названием «поле заголовка страницы». Поэтому я подозреваю, что это закодированные символы, я просто не знаю, какая кодировка. Кто-нибудь знает, что это за символы и какую кодировку я должен использовать для их успешного декодирования?

Похоже на неудачную попытку закодировать "滚动轴承", что по-китайски означает "подшипники". Как вы думаете, почему он вообще закодирован в URL?

Andrey Tyukin 09.04.2019 16:50

А, посмотри сюда: Нестандартные реализации.

Andrey Tyukin 09.04.2019 16:52

О, это действительно имеет смысл! Спасибо!

Sahand 09.04.2019 16:53
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
3
682
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Похоже на нестандартная кодировка на основе UTF-16 "滚动轴承", что по-китайски означает "подшипники".

Я бы предложил просто .replaceAll%u с помощью обратной косой черты, а затем использовать StringEscapeUtils из Apache Commons:

import org.apache.commons.lang3.StringEscapeUtils
val unescapedJava = StringEscapeUtils.unescapeJava(str.replaceAll("%u", "\\u"))
URLDecoder.decode(unescapedJava, StandardCharsets.UTF_8.name())

Это должно обрабатывать оба вида экранирования:

  • Обычные escape-последовательности с %, за которыми следуют цифры, не затрагиваются заменой и unescapeJava
  • Странные %u обрабатываются особым образом (заменяются на \u) и устраняются на первом этапе.

Если (только если) вы абсолютно уверены, что кодовые точки все закодировались таким образом, то можно обойтись без StringEscapeUtils:

new String(
  "%u6EDA%u52A8%u8F74%u627F"
  .replaceAll("%u", "")
  .grouped(4)
  .map(Integer.parseInt(_, 16).toChar)
  .toArray
)

который производит

res: String = 滚动轴承

но я бы посоветовал против этого, потому что этот метод сломается для входные данные, такие как "%u6EDA%u52A8%u8F74%u627Fcafebabe", содержащие неэкранированные символы. Лучше использовать надежный библиотечный метод, который обрабатывает все крайние случаи.

Да, есть и другие строки, декодированные с помощью URL. Спасибо за внимание.

Sahand 09.04.2019 17:35

@Sahand В конце концов, я сохранил шаг с URLEncoder, я думаю, что может быть два случая: стандартный и нестандартный. Сейчас я как бы объединил оба решения.

Andrey Tyukin 09.04.2019 17:37

@Sahand А, спасибо... Я знаю, я забыл об этом u уже три раза подряд, извините. Спасибо. Я думаю, что это должно быть правильно сейчас?

Andrey Tyukin 09.04.2019 17:43

Ваша строка "%u6EDA%u52A8%u8F74%u627F" является синтаксически неверным как строка в кодировке URL. Согласно javadoc URLDecoder.decode и Википедия:Процентное кодирование каждые % должны следовать две шестнадцатеричные цифры.

Может быть, вы хотели использовать "\u6EDA\u52A8\u8F74\u627F" вместо. Это была бы синтаксически правильная строка Java (имеющая 4 шестнадцатеричных экранированных символов Юникода) и эквивалентен "滚动轴承". Но по-прежнему не имеет смысла декодировать URL-адрес этой строки. Поэтому я предполагаю, что ошибка уже произошла на стороне кодирование, который создал эту искаженную строку в кодировке URL в первую очередь.

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

Похожие вопросы

Требуется регулярное выражение для получения идентификаторов электронной почты в сообщении об исключении между символами < и >
Как я могу автоматически обновлять тестовые случаи Rally, используя интеграцию Cucumber и Rally?
Scala, как отсортировать «Нет» снизу, если они существуют, и выбрать первую строку в каждой группе?
Как проверить правильность установки агента YourKit в macOS с помощью терминала с JDK 1.8+
WebDriver для закрытия всплывающего окна через определенное время
Аутентификация Ldap с весенним облачным шлюзом
Я не могу использовать метод invokeHTTP с методом Post в NIFI
Проблема многопоточности -> получение результата потока после его завершения
Как я могу имитировать некоторые вызовы методов bean-компонента, но использовать определенный bean-компонент в вызовах других методов в том же тестовом классе?
Какой самый быстрый способ повернуть только определенные элементы в массиве?