66 votes

Android : comment analyser une chaîne d'URL avec des espaces pour en faire un objet URI ?

J'ai une chaîne représentant une URL contenant des espaces et je veux la convertir en un objet URI. Si j'essaie simplement de le créer via

String myString = "http://myhost.com/media/File Name that has spaces inside.mp3";
URI myUri = new URI(myString);

cela me donne

java.net.URISyntaxException: Illegal character in path at index X

où l'indice X est la position du premier espace dans la chaîne de l'URL.

Comment puis-je analyser myString en un URI objet ?

129voto

BalusC Points 498232

Vous devriez en fait URI-encode les caractères "invalides". Comme la chaîne contient en fait l'URL complète, il est difficile de la coder correctement en URI. Vous ne savez pas quelles barres obliques / doivent être pris en compte et ceux qui ne le sont pas. Vous ne pouvez pas prédire cela sur une String à l'avance. Le problème doit vraiment être résolu à un niveau supérieur. Où est-ce que String venir ? Est-il codé en dur ? Il suffit alors de le modifier vous-même en conséquence. Est-ce qu'il provient d'une entrée utilisateur ? Validez-la et montrez l'erreur, laissez l'utilisateur résoudre lui-même le problème.

De toute façon, si vous pouvez vous assurer qu'il est sólo les espaces dans les URLs qui les rendent invalides, alors vous pouvez aussi simplement faire un remplacement chaîne par chaîne avec %20 :

URI uri = new URI(string.replace(" ", "%20"));

Ou si vous pouvez vous assurer que c'est sólo la partie après le dernier slash qui doit être encodée en URI, vous pouvez également le faire à l'aide de la fonction android.net.Uri classe d'utilité :

int pos = string.lastIndexOf('/') + 1;
URI uri = new URI(string.substring(0, pos) + Uri.encode(string.substring(pos)));

Notez bien que URLEncoder n'est pas adapté à cette tâche, car il est conçu pour coder les noms/valeurs des paramètres de la chaîne de requête conformément à l'article 3.1.1 du règlement. application/x-www-form-urlencoded (telles qu'utilisées dans les formulaires HTML). Voir aussi Codage Java URL des paramètres de la chaîne d'interrogation .

4 votes

@Mannaz - faites juste attention quand un autre symbole "invalide" apparaît dans le nom d'une chanson.

0 votes

@BalusC J'ai essayé URLEncoder.encode("query string", "UTF-8") ; il renvoie le symbole + comme ceci "query+string" où je m'attendais à "%20". J'ai donc utilisé string.replace avec les valeurs codées en dur. Le problème est résolu. Merci pour l'information. Existe-t-il une autre façon de coder au lieu de remplacer manuellement ?

19voto

Bozho Points 273663
java.net.URLEncoder.encode(finalPartOfString, "utf-8");

Cela permettra Codage de l'URL la chaîne.

finalPartOfString est la partie après la dernière barre oblique - dans votre cas, le nom de la chanson, comme il semble.

2 votes

Il codera également les deux-points et les barres obliques, ce qui rendrait l'URL toujours invalide. Il a seulement besoin de coder les espaces pour que l'url soit valide.

0 votes

Ok, ça me fait passer par le URISyntaxException mais maintenant je reçois un 404 du serveur. L'url que j'obtiens est http://myhost.com/media/mp3s/9/Agenda+of+swine+-+13.+Persecu‌​tion+Ascension_+leav‌​e+nothing+standing.m‌​p3 . J'utilise l'URI dans un org.apache.http.client.methods.HttpGet.HttpGet Demande. Des idées ?

0 votes

@Mannaz maintenant c'est une autre chose - vous devez montrer le code du servlet - ou mieux, poser une autre question. Le problème n'est plus sur le client.

1voto

Phileo99 Points 319

Pour gérer les espaces, @ et autres caractères non sécurisés à des emplacements arbitraires dans le chemin de l'URL, utilisez Uri.Builder en combinaison avec une instance locale de l'URL comme je l'ai décrit. ici :

private Uri.Builder builder;
public Uri getUriFromUrl(String thisUrl) {
    URL url = new URL(thisUrl);
    builder =  new Uri.Builder()
                            .scheme(url.getProtocol())
                            .authority(url.getAuthority())
                            .appendPath(url.getPath());
    return builder.build();
}

1voto

siddmuk2005 Points 17
URL url = Test.class.getResource(args[0]);  // reading demo file path from                                                   
                                            // same location where class                                    
File input=null;
try {
    input = new File(url.toURI());
} catch (URISyntaxException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

0 votes

Parce que ça ne répond pas à la question.

1 votes

J'ai donné ceci pour enlever l'espace de l'URL et cela a résolu mon problème parce que pendant la lecture de l'emplacement du fichier, FileInputStream pointe vers null et pendant la lecture avec null, il va lancer Exception mais en utilisant URI je n'ai pas eu le problème.

0voto

hadilq Points 552

J'ai écrit cette fonction :

public static String encode(@NonNull String uriString) {
    if (TextUtils.isEmpty(uriString)) {
        Assert.fail("Uri string cannot be empty!");
        return uriString;
    }
    // getQueryParameterNames is not exist then cannot iterate on queries
    if (Build.VERSION.SDK_INT < 11) {
        return uriString;
    }

    // Check if uri has valid characters
    // See https://tools.ietf.org/html/rfc3986
    Pattern allowedUrlCharacters = Pattern.compile("([A-Za-z0-9_.~:/?\\#\\[\\]@!$&'()*+,;" +
            "=-]|%[0-9a-fA-F]{2})+");
    Matcher matcher = allowedUrlCharacters.matcher(uriString);
    String validUri = null;
    if (matcher.find()) {
        validUri = matcher.group();
    }
    if (TextUtils.isEmpty(validUri) || uriString.length() == validUri.length()) {
        return uriString;
    }

    // The uriString is not encoded. Then recreate the uri and encode it this time
    Uri uri = Uri.parse(uriString);
    Uri.Builder uriBuilder = new Uri.Builder()
            .scheme(uri.getScheme())
            .authority(uri.getAuthority());
    for (String path : uri.getPathSegments()) {
        uriBuilder.appendPath(path);
    }
    for (String key : uri.getQueryParameterNames()) {
        uriBuilder.appendQueryParameter(key, uri.getQueryParameter(key));
    }
    String correctUrl = uriBuilder.build().toString();
    return correctUrl;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X