我期待
System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8"));
输出:
Hello%20World
(20是空格的ASCII十六进制代码)
但是,我得到的是:
Hello+World
我使用的方法错误吗?我应该使用的正确方法是什么?
Answers:
这表现出预期。该URLEncoder
工具实现了有关如何以HTML形式编码URL的HTML规范。
从javadocs:
此类包含用于将String转换为application / x-www-form-urlencoded MIME格式的静态方法。
并来自HTML规范:
应用程序/ x-www-form-urlencoded
使用此内容类型提交的表单必须按以下方式编码:
- 控件名称和值被转义。空格字符替换为“ +”
您将不得不替换它,例如:
System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replace("+", "%20"));
t.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replace("\\+", "%20"));
%20
在URL中将空格编码,+
在表单中将空格编码为提交的数据(内容类型为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,这只会对空间进行编码。请改用库。
这个类执行application/x-www-form-urlencoded
型编码,而不是编码%的,因此更换带
+
是一个正确的行为。
从javadoc:
编码字符串时,以下规则适用:
- 字母数字字符“ a”至“ z”,“ A”至“ Z”以及“ 0”至“ 9”保持不变。
- 特殊字符“。”,“-”,“ *”和“ _”保持不变。
- 空格字符“”转换为加号“ +”。
- 所有其他字符都是不安全的,并且首先使用某种编码方案将其转换为一个或多个字节。然后,每个字节由3个字符的字符串“%xy”表示,其中xy是该字节的两位十六进制表示形式。推荐使用的编码方案是UTF-8。但是,出于兼容性原因,如果未指定编码,则使用平台的默认编码。
url
,空格应解释为%20
。那么我们需要做url.replaceAll("\\+", "%20")
什么?如果是javascript,则不应使用escape
function。使用encodeURI
或encodeURIComponent
代替。那正是我所想。
编码查询参数
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;
}
org.apache.commons.httpclient.util.URIUtil
似乎是解决问题的最有效方法!
Hello+World
这是浏览器如何对请求的表单数据(application/x-www-form-urlencoded
)进行编码GET
,这是URI查询部分通常接受的表单。
http://host/path/?message=Hello+World
如果您将此请求发送到Java servlet,则该servlet将正确解码参数值。通常,这里唯一的问题是编码不匹配。
严格来说,HTTP或URI规范中没有要求要使用application/x-www-form-urlencoded
键值对对查询部分进行编码。查询部分仅需要采用Web服务器接受的形式。实际上,这不太可能成为问题。
将此编码用于URI的其他部分(例如,路径)通常是不正确的。在这种情况下,您应该使用RFC 3986中描述的编码方案。
http://host/Hello%20World
这里更多。
其他答案要么是手动替换字符串,要么是实际编码为HTML格式的URLEncoder,要么是Apache放弃的 URIUtil,或者是使用Guava的UrlEscapers。最后一个很好,除了它不提供解码器。
Apache Commons Lang提供URLCodec,该URLCodec根据URL格式rfc3986进行编码和解码。
String encoded = new URLCodec().encode(str);
String decoded = new URLCodec().decode(str);
如果您已经在使用Spring,则还可以选择使用其 UriUtils类。
刚在Android上也为此苦苦挣扎,设法偶然发现Uri.encode(String,String),而特定于android(android.net.Uri)可能对某些人有用。
静态字符串encoding(String s,String allow)
“ +”是正确的。如果您确实需要%20,则随后自己更换Plusses。
+
在原来的文本字符应该被编码为%2B
。
+
是正确的,至少不了解上下文至少是学问的。不赞成投票。阅读其他答案以了解何时使用+或%20。
这对我有用
org.apache.catalina.util.URLEncoder ul = new org.apache.catalina.util.URLEncoder().encode("MY URL");
尽管已经很老了,但还是可以快速做出反应:
Spring提供了UriUtils-通过它您可以指定如何编码以及与URI相关的部分,例如
encodePathSegment
encodePort
encodeFragment
encodeUriVariables
....
我使用它们是因为我们已经在使用Spring,即不需要附加库!
getForObject
(的一部分RestTemplate
)URL发出测试请求时,它写出的逗号未编码,但对UriUtils.encode(...)
逗号进行了编码,这意味着MockRestServiceServer
如果我使用的输出,则我的路径将不匹配UriUtils.encode
。
检出java.net.URI类。
我使用的方法错误吗?我应该使用的正确方法是什么?
是的,此方法java.net.URLEncoder.encode并非用于根据规范将“”转换为“ 20%”(源)。
空格字符“”转换为加号“ +”。
即使这不是正确的方法,您也可以将其修改为:System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replaceAll("\\+", "%20"));
有一个美好的一天=)。
URLEncoder.encode
)并使用该方法进行修补,replaceAll
该方法仅在此特定情况下有效。请改用正确的类和方法,请参阅其他答案。
使用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();
}
}
ISO-8859-1
对URLEncoder使用字符集“ ”