使用 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 编码字符串。
我正在使用 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 编码字符串。