URLEncoder не может перевести символ пробела



Я жду



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


вывод:



Hello%20World



(20-это ASCII шестнадцатеричный код для пространства)



однако, что я получаю:



Hello+World



Я использую неправильный метод? Какой правильный метод я должен использовать?

745   14  

14 ответов:

это ведет себя так, как ожидалось. Элемент URLEncoder реализует спецификации HTML для кодирования URL-адресов в HTML-формах.

С документации:

этот класс содержит статические методы для преобразование строки в приложение / x-www-form-urlencoded MIME формат.

и спецификация HTML:

application / x-www-form-urlencoded

формы, представленные с этим типом контента должно быть закодировано следующим образом:

  1. имена и значения элементов управления экранируются. Символы пробела заменяются на `+'

вам придется заменить его, например:

System.out.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.заменить, это будет только кодировать пространство. Вместо этого используйте библиотеку.

этот класс выполняет application/x-www-form-urlencoded-тип кодирования, а не процент кодирования, поэтому замена with + - это правильное поведение.

из javadoc:

при кодировании строки применяются следующие правила:

  • буквенно-цифровые символы "a "через" z"," A "через" Z "и" 0 "через" 9 " остаются теми же.
  • специальные символы ".", "-", "*", и " _ " остается тем же самым.
  • пространство символ "" преобразуется в знак плюс "+".
  • все остальные символы небезопасны и сначала преобразуются в один или несколько байтов с помощью некоторой схемы кодирования. Затем каждый байт представляется 3-символьной строкой "%xy", где xy-двузначное шестнадцатеричное представление байта. Рекомендуемая схема кодирования для использования-UTF-8. Однако по соображениям совместимости, если кодировка не указана, то используется кодировка платформы по умолчанию.

кодировать параметры запроса

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

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

больше здесь.

"+" правильный. Если вам действительно нужен %20, то замените плюсы сами после этого.

другие ответы либо представляют собой ручную замену строки, URLEncoder который на самом деле кодирует для формата HTML, Apache бросилURIUtil, или с помощью гуавы это UrlEscapers. Последний в порядке, за исключением того, что он не предоставляет декодер.

Apache Commons Lang предоставляет URLCodec, который кодирует и декодирует в соответствии с форматом URL rfc3986.

String encoded = new URLCodec().encode(str);
String decoded = new URLCodec().decode(str);

Если вы уже используете Spring, вы также можете использовать егоUriUtils класс, а также.

просто боролся с этим тоже на Android, удалось наткнуться на Uri.кодирование (строка, строка) в то время как специфичный для android (android.net.Uri) может быть полезным для некоторых.

статическую строку кодирования(строка с строкой, разрешить)

https://developer.android.com/reference/android/net/Uri.html#encode (java. lang. String, java.ленг.Строка)

это сработало для меня

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

Проверьте класс java.net.URI.

Я использую неправильный метод? Какой правильный метод я должен использовать?

Да, этот метод java. net. URLEncoder. encode не был сделан для преобразования "" в "20%" в соответствии со спецификацией (источник).

символ пробела "" преобразуется в знак плюс "+".

даже это не правильный метод, вы можете изменить это: System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replaceAll("\+", "%20"));хорошего дня =).

хотя и довольно старый, тем не менее быстрый ответ:

Spring предоставляет UriUtils - с помощью этого вы можете указать, как закодировать и какая часть связана с URI, например

encodePathSegment
encodePort
encodeFragment
encodeUriVariables
....

Я использую их, потому что мы уже используем Spring, т. е. никакая дополнительная библиотека не требуется!

использовать 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

Comments

    Ничего не найдено.