使用 UTF-8 使 URLDecoder 崩溃的这些符号是什么?

What are these symbols that crash URLDecoder with 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(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.apply(App.scala:76)
    at scala.App$$anonfun$main.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。我试图阅读这些符号是什么,但我一直没有成功。我在名为 "page title field" 的字段中的数据集中找到了该字符串。所以我怀疑它们是编码符号,我只是不知道是哪种编码。有谁知道这些符号是什么以及我应该使用哪种编码来成功解码它们?

好像是“滚动轴承”的non-standard UTF-16-based encoding,中文是"ball bearings"。

我建议仅使用反斜杠 .replaceAll %u,然后使用 Apache Commons 中的 StringEscapeUtils

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

这应该处理两种转义:

  • 带有 % 后跟数字的正常转义序列不受替换和 unescapeJava
  • 的影响
  • 怪异的%u特殊处理(替换为\u),第一步淘汰

If(仅当)您绝对确定 所有 代码点都以这种方式编码,那么您可以不用 StringEscapeUtils:

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

产生

res: String = 滚动轴承

但我建议不要这样做,因为这种方法会因 像 "%u6EDA%u52A8%u8F74%u627Fcafebabe" 这样包含未转义字符的输入。 最好使用可靠的库方法来处理所有极端情况。

你的字符串"%u6EDA%u52A8%u8F74%u627F" 作为 URL 编码的字符串在语法上是错误的。 根据 URLDecoder.decode 的 javadoc 和 Wikipedia:Percent-encoding 每一个 %后面必须跟两个十六进制数字。

可能是你打算使用 "\u6EDA\u52A8\u8F74\u627F" 反而。这将是一个语法正确的 Java 字符串(有 4 十六进制转义 Unicode 字符),等同于 "滚动轴承"。 但是URL-解码这个字符串仍然没有意义。 因此我猜错误已经发生在 encoding 端, 首先产生了这个格式错误的 URL 编码字符串。