Java URLEncoder无法转换空格字符

Java URLEncoder无法转换空格字符,java,url,urlencode,Java,Url,Urlencode,我期待着 System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8")); 要输出: Hello%20World (20是表示空格的ASCII十六进制代码) 然而,我得到的是: Hello+World 我用错方法了吗?我应该使用的正确方法是什么?“+”是正确的。如果你真的需要%20,那么你可以在以后自己更换多余的东西 警告:这个答案有很大的争议(+8对-6),所以对此持保留态度。对查询参数进行编码 org.apach

我期待着

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

Hello%20World

(20是表示空格的ASCII十六进制代码)

然而,我得到的是:

Hello+World

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

“+”是正确的。如果你真的需要%20,那么你可以在以后自己更换多余的东西

警告:这个答案有很大的争议(+8对-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;
 }
公共静态字符串escapeURIPathParam(字符串输入){
StringBuilder resultStr=新建StringBuilder();
for(char ch:input.toCharArray()){
如果(不安全(ch)){
结果tr.append('%');
结果tr.append(toHex(ch/16));
结果tr.append(toHex(ch%16));
}否则{
结果追加(ch);
}
}
返回resultStr.toString();
}
私有静态字符到十六进制(int-ch){
返回(字符)(ch<10?'0'+ch:A'+ch-10);
}
私有静态布尔值不安全(char ch){
如果(ch>128 | | ch<0)
返回true;
返回“%$&+,/:;=?@#%”。indexOf(ch)>=0;
}

该类执行
应用程序/x-www-form-urlencoded
-类型编码而不是百分比编码,因此将
替换为
+
是正确的行为

从javadoc:

对字符串进行编码时,以下规则适用:

  • 字母数字字符“a”到“z”、“a”到“z”以及“0”到“9”保持不变
  • 特殊字符“.”、“-”和“*”保持不变
  • 空格字符“”被转换为加号“+”
  • 所有其他字符都是不安全的,首先使用某种编码方案将其转换为一个或多个字节。然后,每个字节由3个字符的字符串“%xy”表示,其中xy是字节的两位十六进制表示形式。建议使用的编码方案是UTF-8。但是,出于兼容性原因,如果未指定编码,则使用平台的默认编码

这与预期的一样。
URLEncoder
实现了如何在HTML表单中编码URL的HTML规范

从:

该类包含用于的静态方法 将字符串转换为 application/x-www-form-urlencoded MIME 格式

从以下方面:

应用程序/x-www-form-urlencoded

使用此内容类型提交的表单 必须按如下方式编码:

  • 控件名称和值被转义。空格字符被替换 按“+”键
  • 您必须更换它,例如:

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

    查看java.net.URI类。

    Hello+World
    是浏览器为
    GET
    请求对表单数据(
    application/x-www-form-urlencoded
    )进行编码的方式,这是普遍接受的URI查询部分的表单

    http://host/path/?message=Hello+World
    
    如果将此请求发送到Javaservlet,servlet将正确解码参数值。通常只有编码不匹配时才会出现问题

    严格来说,HTTP或URI规范中没有要求使用
    application/x-www-form-urlencoded
    键值对对对查询部分进行编码;查询部分只需要采用web服务器接受的形式。实际上,这不太可能成为一个问题

    对URI的其他部分(例如路径)使用这种编码通常是不正确的。在这种情况下,应使用中所述的编码方案


    更多信息。

    使用字符集“
    ISO-8859-1
    ”作为URLEncoder

    使用MyUrlEncode.URLencoding(字符串url,字符串enc)来处理此问题

        public class MyUrlEncode {
        static BitSet dontNeedEncoding = null;
        static final int caseDiff = ('a' - 'A');
        static {
            dontNeedEncoding = new BitSet(256);
            int i;
            for (i = 'a'; i <= 'z'; i++) {
                dontNeedEncoding.set(i);
            }
            for (i = 'A'; i <= 'Z'; i++) {
                dontNeedEncoding.set(i);
            }
            for (i = '0'; i <= '9'; i++) {
                dontNeedEncoding.set(i);
            }
            dontNeedEncoding.set('-');
            dontNeedEncoding.set('_');
            dontNeedEncoding.set('.');
            dontNeedEncoding.set('*');
            dontNeedEncoding.set('&');
            dontNeedEncoding.set('=');
        }
        public static String char2Unicode(char c) {
            if(dontNeedEncoding.get(c)) {
                return String.valueOf(c);
            }
            StringBuffer resultBuffer = new StringBuffer();
            resultBuffer.append("%");
            char ch = Character.forDigit((c >> 4) & 0xF, 16);
                if (Character.isLetter(ch)) {
                ch -= caseDiff;
            }
            resultBuffer.append(ch);
                ch = Character.forDigit(c & 0xF, 16);
                if (Character.isLetter(ch)) {
                ch -= caseDiff;
            }
             resultBuffer.append(ch);
            return resultBuffer.toString();
        }
        private static String URLEncoding(String url,String enc) throws UnsupportedEncodingException {
            StringBuffer stringBuffer = new StringBuffer();
            if(!dontNeedEncoding.get('/')) {
                dontNeedEncoding.set('/');
            }
            if(!dontNeedEncoding.get(':')) {
                dontNeedEncoding.set(':');
            }
            byte [] buff = url.getBytes(enc);
            for (int i = 0; i < buff.length; i++) {
                stringBuffer.append(char2Unicode((char)buff[i]));
            }
            return stringBuffer.toString();
        }
        private static String URIEncoding(String uri , String enc) throws UnsupportedEncodingException { //对请求参数进行编码
            StringBuffer stringBuffer = new StringBuffer();
            if(dontNeedEncoding.get('/')) {
                dontNeedEncoding.clear('/');
            }
            if(dontNeedEncoding.get(':')) {
                dontNeedEncoding.clear(':');
            }
            byte [] buff = uri.getBytes(enc);
            for (int i = 0; i < buff.length; i++) {
                stringBuffer.append(char2Unicode((char)buff[i]));
            }
            return stringBuffer.toString();
        }
    
        public static String URLencoding(String url , String enc) throws UnsupportedEncodingException {
            int index = url.indexOf('?');
            StringBuffer result = new StringBuffer();
            if(index == -1) {
                result.append(URLEncoding(url, enc));
            }else {
                result.append(URLEncoding(url.substring(0 , index),enc));
                result.append("?");
                result.append(URIEncoding(url.substring(index+1),enc));
            }
            return result.toString();
        }
    
    }
    
    公共类MyUrlEncode{
    静态位集dontNeedEncoding=null;
    静态final int caseDiff=('a'-'a');
    静止的{
    dontNeedEncoding=新的位集(256);
    int i;
    
    对于(i='a';i一个空格在URL中编码为
    %20
    ,在表单提交的数据(content-type application/x-www-form-urlencoded)中编码为
    +
    。您需要前者

    使用:

    您可以使用:

    String encodedString=UrlEscapers.urlFragmentEscaper().escape(inputString);
    
    不要使用String.replace,这只会对空间进行编码。请改用库。

    这对我很有用

    org.apache.catalina.util.URLEncoder ul = new org.apache.catalina.util.URLEncoder().encode("MY URL");
    
    我用的方法不对吗?我应该用的正确方法是什么

    是的,此方法java.net.URLEncoder.encode不是为根据规范()将“”转换为“20%”而设计的

    空格字符“”被转换为加号“+”


    即使这不是正确的方法,您也可以将其修改为:
    System.out.println(java.net.URLEncoder.encode(“Hello World”,“UTF-8”).replaceAll(\\+”,“%20”);
    祝您有一个美好的一天=)。

    刚刚在Android上也遇到了这个问题,在特定于Android(Android.net.Uri)的时候,成功地发现了Uri.encode(字符串,字符串)可能对某些人有用

    静态字符串编码(字符串s,字符串允许)


    其他答案要么提供手动字符串替换,它实际上为HTML格式、Apache或使用Guava进行编码。最后一个答案很好,只是它不提供解码器

    ApacheCommonsLang提供了,它根据URL格式进行编码和解码


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

    虽然很旧,但是快速响应:

    Spring提供了UriUtils——通过它,您可以指定如何编码以及它与URI的哪个部分相关,例如

    encodePathSegment
    encodePort
    encodeFragment
    encodeUriVariables
    ....
    

    我使用它们是因为我们已经使用了Spring,也就是说,不需要额外的库!

    如果您使用的是jetty,那么
    org.eclipse.jetty.util.URIUtil
    将解决这个问题

    String encoded_string = URIUtil.encodePath(not_encoded_string).toString();
    

    如果您想对URI路径组件进行编码,还可以使用函数,例如

    public static String encodeURLPathComponent(String path) {
        try {
            return new URI(null, null, path, null).toASCIIString();
        } catch (URISyntaxException e) {
            // do some error handling
        }
        return "";
    }
    
    uric
    encodePathSegment
    encodePort
    encodeFragment
    encodeUriVariables
    ....
    
    String encoded_string = URIUtil.encodePath(not_encoded_string).toString();
    
    public static String encodeURLPathComponent(String path) {
        try {
            return new URI(null, null, path, null).toASCIIString();
        } catch (URISyntaxException e) {
            // do some error handling
        }
        return "";
    }
    
    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