URLEncoder не способен переводить символ пробела
Я ожидаю
System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8"));
для вывода:
Hello%20World
(20 - это код ASCII Hex для пробела)
Однако, я получаю:
Hello+World
Использую ли я неправильный метод? Каков правильный метод, который я должен использовать?
Ответы
Ответ 1
Это ведет себя так, как ожидалось. URLEncoder
реализует спецификации HTML для кодирования URL-адресов в форматах HTML.
Из javadocs:
Этот класс содержит статические методы для преобразование строки в application/x-www-form-urlencoded MIME Формат.
и Спецификация HTML:
application/x-www-form-urlencoded
Формы, представленные с этим типом контента должен быть закодирован следующим образом:
- Управляющие имена и значения экранируются. Символы места заменены по `+ '
Вам нужно будет заменить его, например:
System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replace("+", "%20"));
Ответ 2
Этот класс выполняет кодировку типа application/x-www-form-urlencoded
, а не процентное кодирование, поэтому замена
на +
является правильным поведением.
Из javadoc:
При кодировании String применяются следующие правила:
- Буквенно-цифровые символы "a" через "z", "A" через "Z" и "0" - "9" остаются неизменными.
- Специальные символы ".", "-", "*" и "_" остаются неизменными.
- Символ пробела "преобразуется в знак плюса" + ".
- Все остальные символы небезопасны и сначала преобразуются в один или несколько байтов, используя некоторую схему кодирования. Затем каждый байт представлен 3-символьной строкой" % xy", где xy - двухзначное шестнадцатеричное представление байта. Рекомендуемой схемой кодирования для использования является UTF-8. Однако по соображениям совместимости, если кодировка не указана, используется кодировка по умолчанию платформы.
Ответ 3
Пространство кодируется в %20
в URL-адресах и +
в формах переданных данных (приложение типа контента /x -www-form-urlencoded). Вам нужен первый.
Использование Guava:
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, это будет только кодировать пробел. Вместо этого используйте библиотеку.
Ответ 4
Hello+World
заключается в том, как браузер будет кодировать данные формы (application/x-www-form-urlencoded
) для запроса GET
, и это общепринятая форма для части запроса URI.
http://host/path/?message=Hello+World
Если вы отправили этот запрос на сервлет Java, сервлет правильно декодировал значение параметра. Обычно единственное время, когда возникают проблемы, заключается в том, что кодировка не соответствует.
Строго говоря, в спецификациях HTTP или URI нет требования о том, чтобы часть запроса была закодирована с использованием application/x-www-form-urlencoded
пар ключ-значение; часть запроса просто должна быть в форме, которую принимает веб-сервер. На практике это вряд ли будет проблемой.
Как правило, было бы неправильно использовать эту кодировку для других частей URI (например, путь). В этом случае вы должны использовать схему кодирования, как описано в RFC 3986.
http://host/Hello%20World
Подробнее здесь.
Ответ 5
Кодировать параметры запроса
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 " %$&+,/:;[email protected]<>#%".indexOf(ch) >= 0;
}
Ответ 6
"+" является правильным. Если вам действительно нужно %20, то впоследствии замените Плюсы.
Ответ 7
Проверьте класс java.net.URI.
Ответ 8
ИСПОЛЬЗОВАТЬ 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();
}
}
Ответ 9
Это сработало для меня
org.apache.catalina.util.URLEncoder ul = new org.apache.catalina.util.URLEncoder().encode("MY URL");
Ответ 10
Просто борется с этим тоже на Android, сумел наткнуться на Uri.encode(String, String), в то время как конкретный для android (android.net.Uri) может быть полезен для некоторых.
static String encode (String s, String allow)
https://developer.android.com/reference/android/net/Uri.html#encode (java.lang.String, java.lang.String)
Ответ 11
Использую ли я неправильный метод? Каков правильный метод, который я должен использовать?
Да, этот метод java.net.URLEncoder.encode не был сделан для преобразования "в" 20% "в соответствии со спецификацией ( source).
Символ пробела "преобразуется в знак плюса" +".
Даже это не правильный метод, вы можете изменить это: System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replaceAll("\\+", "%20"));
иметь хороший день =).
Ответ 12
используйте набор символов "ISO-8859-1
" для URLEncoder