下面的代码行。
URI url = new URI("http://host?xyz=abc%u021B");
给出了错误:
java.net.URISyntaxException: 在索引19处的转义对格式错误。 http:/host?xyz=abc%u021B。
原因是存在 %u021B
, a 非标准字符编码
有没有一个标准的处理方法?
你可以将"%u021B" -> "\u021B" 然后使用apache.commons.lang3.StringEscapeUtils将其转换为unicode。
例子。
String str = "http://host?xyz=abc%u021B";
str = str.replaceAll("%u", "\\\\u");
str = StringEscapeUtils.unescapeJava(str);
URI uri = new URI(str);
System.out.println("It works!");
System.out.println(str.toString());
有没有标准的处理方法?
以下是 RFC 3986这不是一个有效的URI,正确的行为是拒绝它。
拒绝 WhatWG生活水平 建议采用更稳健的行为,按字面意思处理字符。
否则,如果字节是0x25(%),并且输入中字节后的两个字节不在0x30(0)到0x39(9),0x41(A)到0x46(F),以及0x61(a)到0x66(f)的范围内,全部包括在内,则将字节追加到输出。
由于这个不适用,所以落空,并追加了 %
按原样处理,意思是。
%u021B
被视为等同于。
%25u021B
该 %uxxxx
编码方案是在 草拟-duerst-iri. 如果你想实现它,伪代码将是。
%u([a-f0-9]{4})
b
new String(b, UTF_16BE).getBytes(UTF_8)
%xx
%uxxxx
匹配根据@Roy的回答,这段代码是可行的。
public static URI toUri(String uri) throws URISyntaxException {
StringBuilder stringBuilder = new StringBuilder(uri);
int index = stringBuilder.indexOf("%u");
while (index > -1) {
try {
String substring = stringBuilder.substring(index, index + 6).replaceAll("%u", "\\\\u");
String encoded = URLEncoder.encode(StringEscapeUtils.unescapeJava(substring), StandardCharsets.UTF_8);
stringBuilder.replace(index, index + 6, encoded);
index = stringBuilder.indexOf("%u", index + 6);
} catch (Exception e) {
throw new URISyntaxException(uri, e.getMessage());
}
}
return new URI(stringBuilder.toString());
}
我们的想法是把每一个组 %uxxxx
的编码值,并将其与unicode字符的编码值 \uxxxx
.
这样一来 http://host?xyz=abc%u021B
成为 http://host?xyz=abc%C8%9B
而最后一个是标准URI。