URLEncoder pas capable de traduire un caractère d’espace

je m’attends à

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

pour sortir:

Hello%20World

(20 est le code hexadécimal ASCII pour l’espace)

Cependant, ce que j’obtiens c’est:

Hello+World

Est-ce que j’utilise la mauvaise méthode? Quelle est la bonne méthode que je devrais utiliser?

Cela se comporte comme prévu. L’ URLEncoder implémente les spécifications HTML pour coder les URL dans les formulaires HTML.

Depuis les javadocs :

Cette classe contient des méthodes statiques pour convertir un Ssortingng au format MIME application / x-www-form-urlencoded.

et à partir de la spécification HTML :

application / x-www-form-urlencoded

Les formulaires soumis avec ce type de contenu doivent être encodés comme suit:

  1. Les noms et les valeurs de contrôle sont échappés. Les espaces sont remplacés par «+»

Vous devrez le remplacer, par exemple:

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

Un espace est codé à %20 dans les URL et à + dans les données soumises par les formulaires (type de contenu application / x-www-form-urlencoded). Vous avez besoin du premier.

Utilisation de goyave :

 dependencies { comstack 'com.google.guava:guava:23.0' // or, for Android: comstack 'com.google.guava:guava:23.0-android' } 

Vous pouvez utiliser UrlEscapers :

 Ssortingng encodedSsortingng = UrlEscapers.urlFragmentEscaper().escape(inputSsortingng); 

N’utilisez pas Ssortingng.replace, cela ne coderait que l’espace. Utilisez plutôt une bibliothèque.

Cette classe effectue le codage de type application/x-www-form-urlencoded plutôt que le pourcentage d’encodage, remplaçant ainsi avec + est un comportement correct.

De javadoc:

Lors du codage d’une chaîne, les règles suivantes s’appliquent:

  • Les caractères alphanumériques “a” à “z”, “A” à “Z” et “0” à “9” restnt les mêmes.
  • Les caractères spéciaux “.”, “-“, “*” et “_” restnt les mêmes.
  • Le caractère d’espace “” est converti en un signe plus “+”.
  • Tous les autres caractères sont dangereux et sont d’abord convertis en un ou plusieurs octets en utilisant un schéma de codage. Ensuite, chaque octet est représenté par la chaîne de 3 caractères “% xy”, où xy est la représentation hexadécimale à deux chiffres de l’octet. Le schéma d’encodage recommandé à utiliser est UTF-8. Cependant, pour des raisons de compatibilité, si un codage n’est pas spécifié, le codage par défaut de la plate-forme est utilisé.

Encoder les parameters de la requête

 org.apache.commons.httpclient.util.URIUtil URIUtil.encodeQuery(input); 

OU si vous voulez échapper des caractères dans URI

 public static Ssortingng escapeURIPathParam(Ssortingng input) { SsortingngBuilder resultStr = new SsortingngBuilder(); 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.toSsortingng(); } 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 est la manière dont un navigateur va encoder des données de formulaire ( application/x-www-form-urlencoded ) pour une requête GET et c’est la forme généralement acceptée pour la partie requête d’un URI.

 http://host/path/?message=Hello+World 

Si vous avez envoyé cette requête à un servlet Java, le servlet décodera correctement la valeur du paramètre. Habituellement, le seul problème est que l’encodage ne correspond pas.

À proprement parler, les spécifications HTTP ou URI n’exigent pas que la partie requête soit codée à l’aide de paires clé-valeur application/x-www-form-urlencoded ; la partie requête doit simplement être sous la forme acceptée par le serveur Web. En pratique, il est peu probable que cela pose problème.

Il serait généralement incorrect d’utiliser ce codage pour d’autres parties de l’URI (le chemin par exemple). Dans ce cas, vous devez utiliser le schéma de codage décrit dans la RFC 3986 .

 http://host/Hello%20World 

Plus ici

“+” est correct. Si vous avez vraiment besoin de% 20, remplacez ensuite les autres vous-même.

Les autres réponses présentent soit un remplacement manuel de chaîne, URLEncoder qui encode en fait pour le format HTML, URIUtil abandonné d’ Apache , ou utilisant UrlEscapers de Guava . Le dernier est correct, sauf qu’il ne fournit pas de décodeur.

Apache Commons Lang fournit l’ URLCodec , qui encode et décode selon le format URL rfc3986 .

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

Si vous utilisez déjà Spring, vous pouvez également choisir d’utiliser sa classe UriUtils .

Cela a fonctionné pour moi

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

Juste avoir du mal avec cela aussi sur Android, réussi à trébucher sur Uri.encode (Ssortingng, Ssortingng) alors que spécifique à Android (android.net.Uri) pourrait être utile pour certains.

static Ssortingng encode (Ssortingng s, Ssortingng allow)

https://developer.android.com/reference/android/net/Uri.html#encode(java.lang.Ssortingng, java.lang.Ssortingng)

Découvrez la classe java.net.URI.

Est-ce que j’utilise la mauvaise méthode? Quelle est la bonne méthode que je devrais utiliser?

Oui, cette méthode java.net.URLEncoder.encode n’a pas été faite pour convertir “” à “20%” selon la spécification ( source ).

Le caractère d’espace “” est converti en un signe plus “+”.

Même si ce n’est pas la bonne méthode, vous pouvez modifier ceci: System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replaceAll("\\+", "%20")); bonne journée =).

Bien qu’assez vieux, néanmoins une réponse rapide:

Spring fournit UriUtils – avec ceci vous pouvez spécifier comment encoder et quelle partie est liée à un URI, par exemple

 encodePathSegment encodePort encodeFragment encodeUriVariables .... 

Je les utilise car nous utilisons déjà Spring, c’est-à-dire qu’aucune bibliothèque supplémentaire n’est nécessaire!

UTILISEZ MyUrlEncode.URLencoding (URL de la chaîne, Ssortingng enc) pour gérer le problème

  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.toSsortingng(); } private static Ssortingng URLEncoding(Ssortingng url,Ssortingng enc) throws UnsupportedEncodingException { SsortingngBuffer ssortingngBuffer = new SsortingngBuffer(); 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(); } } 

utiliser le jeu de caractères ” ISO-8859-1 ” pour URLEncoder