Comment obtenir le dernier segment de chemin d'un URI

114

J'ai en entrée une chaîne qui est un URI. comment est-il possible d'obtenir le dernier segment de chemin (qui dans mon cas est un identifiant)?

Ceci est mon URL d'entrée:

String uri = "http://base_path/some_segment/id"

et je dois obtenir l'identifiant que j'ai essayé avec ceci:

String strId = "http://base_path/some_segment/id";
strId = strId.replace(path);
strId = strId.replaceAll("/", "");
Integer id =  new Integer(strId);
return id.intValue();

mais cela ne fonctionne pas, et il doit sûrement y avoir une meilleure façon de le faire.

DX89B
la source

Réponses:

174

est-ce ce que vous recherchez:

URI uri = new URI("http://example.com/foo/bar/42?param=true");
String path = uri.getPath();
String idStr = path.substring(path.lastIndexOf('/') + 1);
int id = Integer.parseInt(idStr);

alternativement

URI uri = new URI("http://example.com/foo/bar/42?param=true");
String[] segments = uri.getPath().split("/");
String idStr = segments[segments.length-1];
int id = Integer.parseInt(idStr);
sfussenegger
la source
49
Je cherchais android.net.Uri d'Android (pas java.net.URI) et je me suis retrouvé ici. Si vous l'utilisez à la place, il existe une méthode appelée getLastPathSegment () qui devrait faire la même chose. :)
pm_labs
5
Faites simplement String idStr = new File(uri.getPath()).getName(), comme cette réponse, mais utilisez Fileau lieu de Stringpour diviser le chemin.
Jason C
cela ne fonctionnera pas pour les URL comme example.com/job/senior-health-and-nutrition-advisor/?param=true . Le dernier "/" crée des problèmes. Besoin de quelque chose de plus bon. La réponse getLastPathSegment () donnée par @paul_sns est parfaite.
Vaibhav Kadam
@VaibhavKadam eh bien, techniquement, vous pourriez affirmer que le dernier segment est une chaîne vide. Mais si ce n'est pas ce que vous voulez, utilisez simplement:while (path.endsWith("/")) path = path.substring(0, path.length() - 1);
sfussenegger
@sfussenegger Mon mauvais je n'ai pas lu les TAG en question. Je pensais qu'il avait l'étiquette d'Android. Eh bien +1 pour android.net.uri. :). Android prend le contrôle de JAVA.
Vaibhav Kadam
69
import android.net.Uri;
Uri uri = Uri.parse("http://example.com/foo/bar/42?param=true");
String token = uri.getLastPathSegment();
Latéral
la source
1
Est-ce "android.net.Uri"? Basez les balises de la question, java.net.URI serait supposé et il n'a pas de getLastPathSegment () ...
Michael Geiser
En outre, le Urinom de la classe Android est en minuscules et ne peut pas être instancié. J'ai corrigé votre réponse pour utiliser la méthode de l'usine statique Uri.parse().
quietmint
GetLastPathSegment n'existe pas ici.
Abdullah Shoaib
2
il a getLastPathSegment () mais cela ne fonctionne pas! renvoie null!
Junia Montana
On dirait que getLastPathSegment () crache au hasard le chemin complet pour moi.
MobDev
48

Voici une courte méthode pour le faire:

public static String getLastBitFromUrl(final String url){
    // return url.replaceFirst("[^?]*/(.*?)(?:\\?.*)","$1);" <-- incorrect
    return url.replaceFirst(".*/([^/?]+).*", "$1");
}

Code de test:

public static void main(final String[] args){
    System.out.println(getLastBitFromUrl(
        "http://example.com/foo/bar/42?param=true"));
    System.out.println(getLastBitFromUrl("http://example.com/foo"));
    System.out.println(getLastBitFromUrl("http://example.com/bar/"));
}

Production:

42
foo
bar

Explication:

.*/      // find anything up to the last / character
([^/?]+) // find (and capture) all following characters up to the next / or ?
         // the + makes sure that at least 1 character is matched
.*       // find all following characters


$1       // this variable references the saved second group from above
         // I.e. the entire string is replaces with just the portion
         // captured by the parentheses above
Sean Patrick Floyd
la source
alors que je suis un grand fan de regex et que je l'utilise fréquemment moi-même, je reconnais que pour la plupart des développeurs, regex est à peu près aussi obtus que possible. ce n'est pas plus simple dans le fait qu'il n'est pas compris rapidement.
Bill Turner
Le /dans la classe de caractères annulée [^/?]est inutile, car il ne sera jamais mis en correspondance. .*/correspondra toujours au dernier / de la chaîne, donc aucun autre /ne doit être rencontré.
Stefan van den Akker
ne fonctionne pas pour ce type de lien http://example.com/foo#reply2, ce serait formidable si vous pouviez mettre à jour votre réponse pour le résoudre. Merci
Seth
23

Je sais que c'est vieux, mais les solutions ici semblent plutôt verbeuses. Juste un one-liner facilement lisible si vous avez un URLou URI:

String filename = new File(url.getPath()).getName();

Ou si vous avez un String:

String filename = new File(new URL(url).getPath()).getName();
Jason C
la source
Cela fonctionne-t-il avec toutes les options possibles d'une URL, comme a.co/last?a=1#frag. Je ne pense pas, comme le code de sous - chaînes du dernier symbole du chemin jusqu'à la fin: path.substring(index + 1).
AlikElzin-kilaka
4
@alik La question demande le dernier segment de chemin. La requête et le fragment ne font pas partie du segment de chemin.
Jason C
13

Si vous utilisez Java 8 et que vous voulez le dernier segment d'un chemin de fichier, vous pouvez le faire.

Path path = Paths.get("example/path/to/file");
String lastSegment = path.getFileName().toString();

Si vous avez une URL comme http://base_path/some_segment/idvous pouvez le faire.

final Path urlPath = Paths.get("http://base_path/some_segment/id");
final Path lastSegment = urlPath.getName(urlPath.getNameCount() - 1);
Will Humphreys
la source
4
Risque car java.nio.file.Paths # get dépend du système de fichiers du système d'exploitation sur lequel la JVM s'exécute. Il n'y a aucune garantie qu'il reconnaîtra un URI avec des barres obliques comme séparateurs de chemin.
Adrian Baker
2
Qu'en est-il de l'URI avec les paramètres de requête? Traiter un URI aléatoire comme un chemin de système de fichiers demande une exception.
Abhijit Sarkar
9

Sous Android

Android a une classe intégrée pour la gestion des URI.

Uri uri = Uri.parse("http://base_path/some_segment/id");
String lastPathSegment = uri.getLastPathSegment()
Brill Pappin
la source
Parfois, cela crache simplement le chemin complet. Je ne sais pas pourquoi ni quand cela semble être aléatoire.
MobDev
Si vous pouvez attraper le contenu qu'il analyse, vous pouvez peut-être configurer un test unitaire pour vous en assurer.
Brill Pappin
8

Dans Java 7+, quelques-unes des réponses précédentes peuvent être combinées pour permettre la récupération de n'importe quel segment de chemin à partir d'un URI, plutôt que juste le dernier segment. Nous pouvons convertir l'URI en java.nio.file.Pathobjet, pour profiter de sa getName(int)méthode.

Malheureusement, la fabrique statique Paths.get(uri)n'est pas conçue pour gérer le schéma http, nous devons donc d'abord séparer le schéma du chemin de l'URI.

URI uri = URI.create("http://base_path/some_segment/id");
Path path = Paths.get(uri.getPath());
String last = path.getFileName().toString();
String secondToLast = path.getName(path.getNameCount() - 2).toString();

Pour obtenir le dernier segment dans une ligne de code, imbriquez simplement les lignes ci-dessus.

Paths.get(URI.create("http://base_path/some_segment/id").getPath()).getFileName().toString()

Pour obtenir l'avant-dernier segment tout en évitant les numéros d'index et le potentiel d'erreurs off-by-one, utilisez la getParent()méthode.

String secondToLast = path.getParent().getFileName().toString();

Notez que la getParent()méthode peut être appelée à plusieurs reprises pour récupérer des segments dans l'ordre inverse. Dans cet exemple, le chemin ne contient que deux segments, sinon l'appel getParent().getParent()récupérerait le troisième au dernier segment.

jaco0646
la source
6

Si vous avez commons-ioinclus dans votre projet, vous pouvez le faire sans créer d'objets inutiles avecorg.apache.commons.io.FilenameUtils

String uri = "http://base_path/some_segment/id";
String fileName = FilenameUtils.getName(uri);
System.out.println(fileName);

Vous donnera la dernière partie du chemin, qui est le id

Bnrdo
la source
3

Vous pouvez utiliser la getPathSegments()fonction. ( Documentation Android )

Considérez votre exemple d'URI:

String uri = "http://base_path/some_segment/id"

Vous pouvez obtenir le dernier segment en utilisant:

List<String> pathSegments = uri.getPathSegments();
String lastSegment = pathSegments.get(pathSegments.size - 1);

lastSegmentsera id.

Sina Masnadi
la source
1

Vous pouvez également utiliser replaceAll:

String uri = "http://base_path/some_segment/id"
String lastSegment = uri.replaceAll(".*/", "")

System.out.println(lastSegment);

résultat:

id
Krzysztof Cichocki
la source
0

J'utilise ce qui suit dans une classe utilitaire:

public static String lastNUriPathPartsOf(final String uri, final int n, final String... ellipsis)
  throws URISyntaxException {
    return lastNUriPathPartsOf(new URI(uri), n, ellipsis);
}

public static String lastNUriPathPartsOf(final URI uri, final int n, final String... ellipsis) {
    return uri.toString().contains("/")
        ? (ellipsis.length == 0 ? "..." : ellipsis[0])
          + uri.toString().substring(StringUtils.lastOrdinalIndexOf(uri.toString(), "/", n))
        : uri.toString();
}
Gerold Broser
la source
-1

Obtenez l'URL à partir de l'URI et utilisez getFile () si vous n'êtes pas prêt à utiliser la méthode de sous-chaîne pour extraire le fichier.

Nageswara Rao
la source
2
ne fonctionnera pas, voir javadoc de getFile (): Obtient le nom de fichier de cette URL. La partie du fichier retourné sera la même que getPath (), plus la concaténation de la valeur de getQuery (), le cas échéant. S'il n'y a pas de partie de requête, cette méthode et getPath () renverront des résultats identiques.)
sfussenegger
N'utilisez getPath()pas getFile().
Jason C