我在期待

System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8"));

输出:

你好%20世界

(20是ASCII十六进制空格码)

然而,我得到的是:

你好+世界

我用错方法了吗?我应该使用的正确方法是什么?


当前回答

它不是一行代码,但是你可以使用:

URL url = new URL("https://some-host.net/dav/files/selling_Rosetta Stone Case Study.png.aes");
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
System.out.println(uri.toString());

这将给你一个输出:

https://some-host.net/dav/files/selling_Rosetta%20Stone%20Case%20Study.png.aes

其他回答

其他答案要么提供手动字符串替换,实际上编码HTML格式的URLEncoder, Apache放弃的URIUtil,或者使用Guava的UrlEscapers。最后一个很好,除了它没有提供解码器。

Apache Commons Lang提供了URLCodec,它根据URL格式rfc3986进行编码和解码。

String encoded = new URLCodec().encode(str);
String decoded = new URLCodec().decode(str);

如果您已经在使用Spring,您也可以选择使用它的UriUtils类。

“+”是正确的。如果你真的需要%20,然后自己替换加。

警告:这个答案有很大的争议(+8 vs. -6),所以对这个答案持保留态度。

查询参数

org.apache.commons.httpclient.util.URIUtil
    URIUtil.encodeQuery(input);

如果你想转义URI中的字符

public static String escapeURIPathParam(String input) {
  StringBuilder resultStr = new StringBuilder();
  for (char ch : input.toCharArray()) {
   if (isUnsafe(ch)) {
    resultStr.append('%');
    resultStr.append(toHex(ch / 16));
    resultStr.append(toHex(ch % 16));
   } else{
    resultStr.append(ch);
   }
  }
  return resultStr.toString();
 }

 private static char toHex(int ch) {
  return (char) (ch < 10 ? '0' + ch : 'A' + ch - 10);
 }

 private static boolean isUnsafe(char ch) {
  if (ch > 128 || ch < 0)
   return true;
  return " %$&+,/:;=?@<>#%".indexOf(ch) >= 0;
 }

我已经在使用Feign了,所以我可以使用UriUtils,但Spring UrlUtils不行。

<!-- https://mvnrepository.com/artifact/io.github.openfeign/feign-core -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-core</artifactId>
    <version>11.8</version>
</dependency>

我的模拟测试代码:

import feign.template.UriUtils;

System.out.println(UriUtils.encode("Hello World"));

输出:

你好%20世界

正如该类所暗示的,它编码uri而不是url,但OP要求的是uri而不是url。

System.out.println(UriUtils.encode("https://some-host.net/dav/files/selling_Rosetta Stone Case Study.png.aes"));

输出:

2F https 3A % % 2Fsome-host。网2Fdav % 2Ffiles 2Fselling_Rosetta % 20Stone 20Case % 20Study png。aes

如果你想编码URI路径组件,你也可以使用标准的JDK函数,例如:

public static String encodeURLPathComponent(String path) {
    try {
        return new URI(null, null, path, null).toASCIIString();
    } catch (URISyntaxException e) {
        // do some error handling
    }
    return "";
}

URI类还可以用于编码URI的不同部分或整个URI。