java.net.URI非标准编码的Unicode字符错误。

问题描述 投票:1回答:2

下面的代码行。

    URI url = new URI("http://host?xyz=abc%u021B");

给出了错误:

java.net.URISyntaxException: 在索引19处的转义对格式错误。 http:/host?xyz=abc%u021B。

原因是存在 %u021B, a 非标准字符编码

有没有一个标准的处理方法?

java unicode urlencode
2个回答
1
投票

你可以将"%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());

1
投票

有没有标准的处理方法?

以下是 RFC 3986这不是一个有效的URI,正确的行为是拒绝它。

拒绝 WhatWG生活水平 建议采用更稳健的行为,按字面意思处理字符。

否则,如果字节是0x25(%),并且输入中字节后的两个字节不在0x30(0)到0x39(9),0x41(A)到0x46(F),以及0x61(a)到0x66(f)的范围内,全部包括在内,则将字节追加到输出。

由于这个不适用,所以落空,并追加了 % 按原样处理,意思是。

%u021B

被视为等同于。

%25u021B

%uxxxx 编码方案是在 草拟-duerst-iri. 如果你想实现它,伪代码将是。

  1. Match on %u([a-f0-9]{4})
  2. 将十六进制数字解析为一个字节数组。b
  3. 拿着 new String(b, UTF_16BE).getBytes(UTF_8)
  4. 附加 结果中的每个字节为 %xx
  5. 替换原有的 %uxxxx 匹配

0
投票

根据@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。

© www.soinside.com 2019 - 2024. All rights reserved.