这些符号会使URLDecoder与UTF-8崩溃?

时间:2019-04-09 14:45:04

标签: java scala url unicode decoding

我正在使用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 个答案:

答案 0 :(得分:2)

就像non-standard UTF-16-based encoding的“滚动轴承”,它的中文意思是“滚珠轴承”。

我建议只用反斜杠.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代替),并在第一步中将其消除。

如果(仅当您)完全确定所有个代码点都采用这种方式编码时,则可以不用StringEscapeUtils

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

产生

res: String = 滚动轴承

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

答案 1 :(得分:1)

您的字符串"%u6EDA%u52A8%u8F74%u627F" 从语法上讲,作为URL编码的字符串是错误的。 根据{{​​3}}的javadoc, 每个URLDecoder.decode %后必须跟两个十六进制数字。

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