URLEncoder无法翻译空格字符

我期待

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

输出:

Hello%20World

(20是空格的ASCIIhex代码)

但是,我得到的是:

Hello+World

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

这performance如预期。 URLEncoder实现HTML规范如何在HTML表单中编码URL。

javadocs

该类包含将string转换为application / x-www-form-urlencoded MIME格式的静态方法。

并从HTML规范

应用程序/ x-WWW窗体-urlencoded

使用此内容types提交的表单必须编码如下:

  1. 控制名称和值被转义。 空格字符被replace为“+”

你将不得不取代它,例如:

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

这个类执行application/x-www-form-urlencodedtypes编码而不是百分比编码,因此replace +是一个正确的行为。

来自javadoc:

编码string时,应用下列规则:

  • 字母数字字符“a”到“z”,“A”到“Z”和“0”到“9”保持不变。
  • 特殊字符“。”,“ – ”,“*”和“_”保持不变。
  • 空格字符“”被转换成加号“+”。
  • 所有其他字符都是不安全的,首先使用某种编码scheme将其转换为一个或多个字节。 然后每个字节由3个字符的string“%xy”表示,其中xy是该字节的两位hex表示。 推荐使用的编码scheme是UTF-8。 但是,出于兼容性原因,如果未指定编码,则使用平台的默认编码。

空格在URL中被编码为%20 ,在提交的数据(内容types为application / x-www-form-urlencoded)中被编码为+ 。 你需要前者。

使用番石榴 :

 dependencies { compile 'com.google.guava:guava:23.0' // or, for Android: compile 'com.google.guava:guava:23.0-android' } 

你可以使用UrlEscapers :

 String encodedString = UrlEscapers.urlFragmentEscaper().escape(inputString); 

不要使用String.replace,这只会编码空间。 使用库来代替。

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

 http://host/path/?message=Hello+World 

如果您将此请求发送给Java Servlet,则Servlet将正确解码参数值。 通常这里唯一的问题是编码不匹配。

严格地说,在HTTP或URI规范中没有要求使用application/x-www-form-urlencoded键值对来编码查询部分; 查询部分只需要在Web服务器接受的forms。 在实践中,这不太可能是一个问题。

对URI的其他部分(例如path)使用这种编码通常是不正确的。 在这种情况下,您应该使用RFC 3986中描述的编码scheme。

 http://host/Hello%20World 

更多在这里 。

编码查询参数

 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; } 

“+”是正确的。 如果你真的需要%20,那么在之后你自己更换。

查看java.net.URI类。

使用MyUrlEncode.URLencoding(String url,String 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(); } } 

这对我有效

 org.apache.catalina.util.URLEncoder ul = new org.apache.catalina.util.URLEncoder().encode("MY URL"); 

刚刚在Android上也一直在挣扎,设法绊倒Uri.encode(string,string),而具体到android(android.net.Uri)可能是有用的一些。

静态string编码(String s,string允许)

https://developer.android.com/reference/android/net/Uri.html#encode(java.lang.String,java.lang.String);

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

是的,这个方法java.net.URLEncoder.encode没有根据spec( source )将“”转换为“20%”。

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

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

对URLEncoder使用字符集“ ISO-8859-1