Android: Comment analyser la chaîne D'URL avec les espaces de L'objet URI?
j'ai une chaîne représentant une URL contenant des espaces et je veux la convertir à un objet URI. Si est simple, essayez de faire des
String myString = "http://myhost.com/media/mp3s/9/Agenda of swine - 13. Persecution Ascension_ leave nothing standing.mp3";
URI myUri = new URI(myString);
il me donne
java.net.URISyntaxException: Illegal character in path at index X
où l'index X
est la position du premier espace dans la chaîne D'URL.
Comment puis-je analyser myString
en un objet URI
?
5 réponses
vous devriez en fait URI-encoder les caractères" invalides". Comme la chaîne contient en fait L'URL complète, il est difficile de L'URI-encoder correctement. Vous ne savez pas quels slashs /
doivent être pris en compte et lesquels Non. Vous ne pouvez pas prédire cela sur un raw String
à l'avance. Le problème doit être résolu à un niveau supérieur. D'où vient ce String
? Est-il figé? Alors changez-le vous-même en conséquence. Faire venez en tant que saisie de l'utilisateur? Valider et afficher l'erreur, laisser l'utilisateur se résoudre lui-même.
de toute façon, si vous pouvez vous assurer que ce sont seulement les espaces dans les URLs qui le rendent invalide, alors vous pouvez aussi juste 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 seulement la partie après le dernier slash qui doit être URI codé, alors vous pouvez aussi le faire avec aide de android.net.Uri
classe d'utilité:
int pos = string.lastIndexOf('/') + 1;
URI uri = new URI(string.substring(0, pos) + Uri.encode(string.substring(pos)));
Ne remarque que URLEncoder
est insuitable pour la tâche car il est conçu pour encoder paramètre de chaîne de requête noms/valeurs par application/x-www-form-urlencoded
règles (comme utilisé dans les formulaires HTML). Voir aussi Java URL encodage des paramètres de chaîne de requête .
java.net.URLEncoder.encode(finalPartOfString, "utf-8");
ce sera URL-Encoder la chaîne de caractères.
finalPartOfString
est la partie après le dernier slash - dans votre cas, le nom de la chanson, comme il semble.
pour gérer les espaces, @, et autres caractères dangereux dans des emplacements arbitraires dans le chemin d'url, utilisez Uri.Builder en combinaison avec une instance locale D'URL comme j'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();
}
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();
}
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;
}