我在期待
System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8"));
输出:
你好%20世界
(20是ASCII十六进制空格码)
然而,我得到的是:
你好+世界
我用错方法了吗?我应该使用的正确方法是什么?
我在期待
System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8"));
输出:
你好%20世界
(20是ASCII十六进制空格码)
然而,我得到的是:
你好+世界
我用错方法了吗?我应该使用的正确方法是什么?
查询参数
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;
}
该类执行application/x-www-form- urlenencoded -type编码,而不是百分比编码,因此替换为+是正确的行为。
从javadoc:
When encoding a String, the following rules apply: The alphanumeric characters "a" through "z", "A" through "Z" and "0" through "9" remain the same. The special characters ".", "-", "*", and "_" remain the same. The space character " " is converted into a plus sign "+". All other characters are unsafe and are first converted into one or more bytes using some encoding scheme. Then each byte is represented by the 3-character string "%xy", where xy is the two-digit hexadecimal representation of the byte. The recommended encoding scheme to use is UTF-8. However, for compatibility reasons, if an encoding is not specified, then the default encoding of the platform is used.
这是预期的行为。URLEncoder实现了如何在HTML表单中编码url的HTML规范。
来自javadocs:
该类包含的静态方法 将String转换为 应用程序/ x-www-form-urlencoded MIME 格式。
和来自HTML规范:
应用程序/ x-www-form-urlencoded 使用此内容类型提交的表单 必须编码如下: 控件名称和值被转义。空格字符被替换 通过“+”
你必须更换它,例如:
System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replace("+", "%20"));
Hello+World是浏览器为GET请求编码表单数据(application/x-www-form-urlencoded)的方式,这是URI查询部分的普遍接受的形式。
http://host/path/?message=Hello+World
如果将此请求发送到Java servlet, servlet将正确解码参数值。通常唯一出现问题的情况是编码不匹配。
严格来说,HTTP或URI规范中没有要求使用application/x-www-form- urlenencoded键-值对对查询部分进行编码;查询部分只需采用web服务器接受的形式即可。实际上,这不大可能成为一个问题。
对于URI的其他部分(例如路径)使用这种编码通常是不正确的。在这种情况下,您应该使用RFC 3986中描述的编码方案。
http://host/Hello%20World
更多的在这里。
使用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();
}
}
一个空格在url中被编码为%20,在表单提交的数据中被编码为+(内容类型为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。替换,这只会编码空间。使用库代替。
这对我很有效
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上也在挣扎,设法偶然发现了Uri。encode(字符串,字符串)而特定于android (android.net.Uri)可能对一些有用。
静态字符串编码(字符串s,字符串允许)
以https://developer.android.com/reference/android/net/Uri.html编码(以)
其他答案要么提供手动字符串替换,实际上编码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类。
虽然很老了,但还是迅速回应:
Spring提供了UriUtils -使用它你可以指定如何编码以及它与URI的哪个部分相关。
encodePathSegment
encodePort
encodeFragment
encodeUriVariables
....
我使用它们是因为我们已经在使用Spring,即不需要额外的库!
如果您正在使用jetty,那么org.eclipse.jetty.util.URIUtil将解决这个问题。
String encoded_string = URIUtil.encodePath(not_encoded_string).toString();
如果你想编码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。
它不是一行代码,但是你可以使用:
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
试试下面的方法:
添加一个新的依赖项
<!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-catalina -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>10.0.13</version>
</dependency>
现在按照下面的步骤做:
String str = "Hello+World"; // For "Hello World", decoder is not required
// import java.net.URLDecoder;
String newURL = URLDecoder.decode(str, StandardCharsets.UTF_8);
// import org.apache.catalina.util.URLEncoder;
System.out.println(URLEncoder.DEFAULT.encode(newURL, StandardCharsets.UTF_8));
你会得到如下的输出:
Hello%20World
我已经在使用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