Что это за символы, которые вызывают сбой URLDecoder с UTF-8? - PullRequest
2 голосов
/ 09 апреля 2019

Я использую 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 недопустимы в строке. Я пытался прочитать, что это за символы, но мне это не удалось. Я нашел строку в наборе данных в поле под названием «поле заголовка страницы». Так что я подозреваю, что это кодированные символы, я просто не знаю, какую кодировку. Кто-нибудь знает, что это за символы и какую кодировку я должен использовать для их успешного декодирования?

Ответы [ 2 ]

3 голосов
/ 09 апреля 2019

Похоже на нестандартную кодировку на основе 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", которые содержат символы без экранирования Лучше использовать надежный библиотечный метод, который обрабатывает все угловые случаи.

2 голосов
/ 09 апреля 2019

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

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

...