web-dev-qa-db-fra.com

Java - Convertir une chaîne en objet URI valide

J'essaie d'obtenir un objet Java.net.URI à partir d'une String. La chaîne contient des caractères qui devront être remplacés par leurs séquences d'échappement en pourcentage. Mais lorsque j'utilise URLEncoder pour coder la chaîne avec le codage UTF-8, même les/sont remplacés par leurs séquences d'échappement.

Comment puis-je obtenir une URL encodée valide à partir d'un objet String?

http://www.google.com?q=a b donne http% 3A% 2F% 2www.google.com ... alors que je veux que le résultat soit http://www.google.com?q=a%20b

Quelqu'un peut-il s'il vous plaît me dire comment y parvenir.

J'essaie de faire cela dans une application Android. J'ai donc accès à un nombre limité de bibliothèques.

69
lostInTransit

Vous pouvez essayer: org.Apache.commons.httpclient.util.URIUtil.encodeQuery dans Apache commons-httpclient project

Comme ceci (voir URIUtil ):

URIUtil.encodeQuery("http://www.google.com?q=a b")

va devenir:

http://www.google.com?q=a%20b

Vous pouvez bien sûr le faire vous-même, mais l'analyse URI peut devenir assez compliquée ...

55
Hans Doggen

Android a toujours eu la classe Uri dans le SDK: http://developer.Android.com/reference/Android/net/Uri.html

Vous pouvez simplement faire quelque chose comme:

String requestURL = String.format("http://www.example.com/?a=%s&b=%s", Uri.encode("foo bar"), Uri.encode("100% fubar'd"));
45
bensnider

Je vais ajouter une suggestion ici destinée aux utilisateurs d'Android. Vous pouvez le faire, ce qui évite d'avoir à utiliser des bibliothèques externes. En outre, toutes les solutions de recherche/remplacement de caractères suggérées dans certaines des réponses ci-dessus sont périlleuses et doivent être évitées. 

Essayez ceci:

String urlStr = "http://abc.dev.domain.com/0007AC/ads/800x480 15sec h.264.mp4";
URL url = new URL(urlStr);
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
url = uri.toURL();

Vous pouvez voir que dans cette URL particulière, je dois coder ces espaces pour pouvoir l'utiliser pour une requête. 

Cela tire parti de quelques fonctionnalités disponibles dans les classes Android. Tout d'abord, la classe d'URL peut fractionner une URL en ses propres composants, vous évitant ainsi de devoir effectuer un travail de recherche/remplacement de chaîne. Deuxièmement, cette approche tire parti de la fonctionnalité de classe d'URI consistant à échapper correctement les composants lorsque vous construisez un URI via des composants plutôt qu'à partir d'une seule chaîne.

La beauté de cette approche réside dans le fait que vous pouvez prendre n'importe quelle chaîne d'URL valide et la faire fonctionner sans avoir besoin de connaissances particulières de votre part. 

33
Craig B

Même s'il s'agit d'un ancien message avec une réponse déjà acceptée, je poste ma réponse alternative car cela fonctionne bien pour le présent numéro et il semble que personne n'ait mentionné cette méthode.

Avec la bibliothèque Java.net.URI:

URI uri = URI.create(URLString);

Et si vous voulez une chaîne au format URL correspondante:

String validURLString = uri.toASCIIString();

Contrairement à beaucoup d'autres méthodes (par exemple, Java.net.URLEncoder), celle-ci ne remplace que les caractères non sécurisés ASCII (comme ç, é...).


Dans l'exemple ci-dessus, si URLString est la suivante String:

"http://www.domain.com/façon+Word"

la validURLString résultante sera:

"http://www.domain.com/fa%C3%A7on+Word"

qui est une URL bien formatée.

14
dgiugg

Si vous n'aimez pas les bibliothèques, pourquoi pas ça?

Notez que vous ne devez pas utiliser cette fonction sur l'URL complète, mais plutôt sur les composants ... par exemple. juste le composant "a b", au fur et à mesure que vous construisez l'URL - sinon, l'ordinateur ne saura pas quels caractères sont supposés avoir une signification spéciale et lesquels sont supposés avoir une signification littérale.

/** Converts a string into something you can safely insert into a URL. */
public static String encodeURIcomponent(String s)
{
    StringBuilder o = new StringBuilder();
    for (char ch : s.toCharArray()) {
        if (isUnsafe(ch)) {
            o.append('%');
            o.append(toHex(ch / 16));
            o.append(toHex(ch % 16));
        }
        else o.append(ch);
    }
    return o.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;
}
9
Tim Cooper

Vous pouvez utiliser les constructeurs multi-arguments de la classe URI. De la URI javadoc:

Les constructeurs multi-arguments citent les caractères non autorisés comme requis par les composants dans lesquels ils apparaissent. Le caractère de pourcentage ('%') est toujours cité par ces constructeurs. Tous les autres caractères sont conservés.

Donc si vous utilisez

URI uri = new URI("http", "www.google.com?q=a b");

Ensuite, vous obtenez http:www.google.com?q=a%20b qui n'est pas tout à fait correct, mais c'est un peu plus proche.

Si vous savez que votre chaîne ne comportera pas de fragments d'URL (par exemple, http://example.com/page#anchor ), vous pouvez utiliser le code suivant pour obtenir ce que vous voulez:

String s = "http://www.google.com?q=a b";
String[] parts = s.split(":",2);
URI uri = new URI(parts[0], parts[1], null);

Pour des raisons de sécurité, vous devez analyser la chaîne pour connaître les caractères #, mais cela devrait vous aider à démarrer.

4
Jason Day

J'ai eu des problèmes similaires pour l'un de mes projets pour créer un objet URI à partir d'une chaîne. Je n'ai pas pu trouver de solution propre non plus. Voici ce que je suis venu avec:

public static URI encodeURL(String url) throws MalformedURLException, URISyntaxException  
{
    URI uriFormatted = null; 

    URL urlLink = new URL(url);
    uriFormatted = new URI("http", urlLink.getHost(), urlLink.getPath(), urlLink.getQuery(), urlLink.getRef());

    return uriFormatted;
}

Vous pouvez utiliser le constructeur d'URI suivant pour spécifier un port si nécessaire:

URI uri = new URI(scheme, userInfo, Host, port, path, query, fragment);
4
Hervé Donner

Eh bien j'ai essayé d'utiliser 

String converted = URLDecoder.decode("toconvert","UTF-8");

J'espère que c'est ce que vous cherchiez réellement?

3
Amol Ghotankar

Ou peut-être pourriez-vous utiliser cette classe:

http://developer.Android.com/reference/Java/net/URLEncoder.html

Qui est présent dans Android depuis le niveau 1 de l’API.

Malheureusement, il traite les espaces spécialement (en les remplaçant par + au lieu de% 20). Pour contourner ce problème, nous utilisons simplement ce fragment:

URLEncoder.encode(value, "UTF-8").replace("+", "%20");

1
MrCranky

L’autre jour, le blog Java.net proposait un cours qui aurait pu faire ce que vous souhaitiez (mais il est en panne pour le moment et je ne peux pas vérifier). 

Ce code ici pourrait probablement être modifié pour faire ce que vous voulez:

http://svn.Apache.org/repos/asf/incubator/shindig/trunk/Java/common/src/main/Java/org/Apache/shindig/common/uri/UriBuilder.Java

Voici celui auquel je pensais de Java.net: https://urlencodedquerystring.dev.Java.net/

1
TofuBeer

J'ai fini par utiliser le httpclient-4.3.6:

import org.Apache.http.client.utils.URIBuilder;
public static void main (String [] args) {
    URIBuilder uri = new URIBuilder();
    uri.setScheme("http")
    .setHost("www.example.com")
    .setPath("/somepage.php")
    .setParameter("username", "Hello Günter")
    .setParameter("p1", "parameter 1");
    System.out.println(uri.toString());
}

La sortie sera:

http://www.example.com/somepage.php?username=Hello+G%C3%BCnter&p1=paramter+1
0