URLEncoder не может перевести символ пробела
Я жду
System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8"));
вывод:
Hello%20World
(20-это ASCII шестнадцатеричный код для пространства)
однако, что я получаю:
Hello+World
Я использую неправильный метод? Какой правильный метод я должен использовать?
14 ответов:
это ведет себя так, как ожидалось. Элемент
URLEncoderреализует спецификации HTML для кодирования URL-адресов в HTML-формах.С документации:
этот класс содержит статические методы для преобразование строки в приложение / x-www-form-urlencoded MIME формат.
application / x-www-form-urlencoded
формы, представленные с этим типом контента должно быть закодировано следующим образом:
- имена и значения элементов управления экранируются. Символы пробела заменяются на `+'
вам придется заменить его, например:
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больше здесь.
другие ответы либо представляют собой ручную замену строки, 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) может быть полезным для некоторых.
статическую строку кодирования(строка с строкой, разрешить)
это сработало для меня
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"));хорошего дня =).
хотя и довольно старый, тем не менее быстрый ответ:
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(); } }
Comments