Cómo obtener el último segmento de ruta de un URI

114

Tengo como entrada una cadena que es un URI. ¿Cómo es posible obtener el último segmento de ruta (que en mi caso es una identificación)?

Esta es mi URL de entrada:

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

y tengo que obtener la identificación que he probado con esto:

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

pero no funciona, y seguramente debe haber una mejor manera de hacerlo.

DX89B
fuente

Respuestas:

174

Es esto lo que estás buscando:

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);

alternativamente

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
fuente
49
Estaba buscando android.net.Uri de Android (no java.net.URI) y terminé aquí. Si está usando eso en su lugar, hay un método llamado getLastPathSegment () que debería hacer lo mismo. :)
pm_labs
5
Simplemente haga lo String idStr = new File(uri.getPath()).getName()mismo que esta respuesta, pero usa en Filelugar de Stringdividir la ruta.
Jason C
esto no funcionará para URL como example.com/job/senior-health-and-nutrition-advisor/?param=true . La última "/" está causando problemas. Necesito algo más bueno getLastPathSegment () La respuesta dada por @paul_sns es perfecta.
Vaibhav Kadam
@VaibhavKadam bueno, técnicamente se podría argumentar que el último segmento es una cadena vacía. Pero si eso no es lo que desea, simplemente use:while (path.endsWith("/")) path = path.substring(0, path.length() - 1);
sfussenegger
@sfussenegger Mi mal no leí TAGs en cuestión. Pensé que tenía la etiqueta de Android. Bueno, +1 para android.net.uri. :). Android se está apoderando 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();
Colateral
fuente
1
¿Es esto "android.net.Uri"? Con base en las etiquetas de la pregunta, se supondría java.net.URI y no tiene un getLastPathSegment () ...
Michael Geiser
Además, el Urinombre de la clase de Android está en minúsculas y no se puede crear una instancia. He corregido su respuesta para utilizar el método de fábrica estática Uri.parse().
quietmint
GetLastPathSegment no existe aquí.
Abdullah Shoaib
2
tiene getLastPathSegment () pero no funciona. devuelve nulo!
Junia Montana
Parece que getLastPathSegment () escupe aleatoriamente la ruta completa para mí.
MobDev
48

Aquí hay un método breve para hacerlo:

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

Código de prueba:

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/"));
}

Salida:

42 barra de
foo

Explicación:

.*/      // 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
fuente
Si bien soy un gran fanático de las expresiones regulares y las uso con frecuencia, reconozco que para la mayoría de los desarrolladores, las expresiones regulares son tan obtusas como parece. no es más simple en el hecho de que no se comprende rápidamente.
Bill Turner
El /en la clase de carácter negado [^/?]es innecesario, porque nunca coincidirá. .*/siempre coincidirá con el último / de la cadena, por lo que no se /debe encontrar ningún otro .
Stefan van den Akker
no funciona para este tipo de enlace http://example.com/foo#reply2. Sería genial si pudieras actualizar tu respuesta para resolverlo. Gracias
Seth
23

Sé que esto es antiguo, pero las soluciones aquí parecen bastante detalladas. Solo un resumen de fácil lectura si tiene URLo URI:

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

O si tiene un String:

String filename = new File(new URL(url).getPath()).getName();
Jason C
fuente
¿Funciona con todas las opciones posibles de una URL, como a.co/last?a=1#frag. Creo que no, ya que el código no subcadena del último símbolo camino hasta el final: path.substring(index + 1).
AlikElzin-kilaka
4
@alik La pregunta solicita el último segmento de la ruta. La consulta y el fragmento no forman parte del segmento de la ruta.
Jason C
13

Si está utilizando Java 8 y desea el último segmento en una ruta de archivo, puede hacerlo.

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

Si tiene una URL como http://base_path/some_segment/idpuede hacer.

final Path urlPath = Paths.get("http://base_path/some_segment/id");
final Path lastSegment = urlPath.getName(urlPath.getNameCount() - 1);
Will Humphreys
fuente
4
Es arriesgado porque java.nio.file.Paths # get depende del sistema de archivos del sistema operativo en el que se ejecuta la JVM. No hay garantía de que reconozca un URI con barras diagonales como separadores de ruta.
Adrian Baker
2
¿Qué pasa con URI con parámetros de consulta? Tratar un URI aleatorio como una ruta del sistema de archivos es solicitar una excepción.
Abhijit Sarkar
9

En Android

Android tiene una clase integrada para administrar URI.

Uri uri = Uri.parse("http://base_path/some_segment/id");
String lastPathSegment = uri.getLastPathSegment()
Brill Pappin
fuente
A veces, esto simplemente escupe el camino completo. No estoy seguro de por qué o cuándo parece ser aleatorio.
MobDev
Si puede captar el contenido que está analizando, tal vez pueda configurar una prueba unitaria para asegurarse.
Brill Pappin
8

En Java 7+, algunas de las respuestas anteriores se pueden combinar para permitir la recuperación de cualquier segmento de ruta de un URI, en lugar de solo el último segmento. Podemos convertir el URI en un java.nio.file.Pathobjeto, para aprovechar sugetName(int) método.

Desafortunadamente, la fábrica estática Paths.get(uri)no está construida para manejar el esquema http, por lo que primero debemos separar el esquema de la ruta del 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();

Para obtener el último segmento en una línea de código, simplemente anide las líneas de arriba.

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

Para obtener el penúltimo segmento evitando los números de índice y la posibilidad de errores uno por uno, utilice el getParent()método.

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

Tenga en cuenta que el getParent()método se puede llamar repetidamente para recuperar segmentos en orden inverso. En este ejemplo, la ruta solo contiene dos segmentos; de lo contrario, la llamada getParent().getParent()recuperaría el antepenúltimo segmento.

jaco0646
fuente
6

Si lo ha commons-ioincluido en su proyecto, puede hacerlo sin crear objetos innecesarios conorg.apache.commons.io.FilenameUtils

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

Te dará la última parte del camino, que es el id

Bnrdo
fuente
3

Puede utilizar la getPathSegments()función. ( Documentación de Android )

Considere su URI de ejemplo:

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

Puede obtener el último segmento usando:

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

lastSegmentserá id.

Sina Masnadi
fuente
1

También puede usar replaceAll:

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

System.out.println(lastSegment);

resultado:

id
Krzysztof Cichocki
fuente
0

Estoy usando lo siguiente en una clase de utilidad:

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
fuente
-1

Obtenga la URL de URI y use getFile () si no está listo para usar la forma de subcadena de extraer el archivo.

Nageswara Rao
fuente
2
no funcionará, vea javadoc de getFile (): Obtiene el nombre de archivo de esta URL. La parte del archivo devuelto será la misma que getPath (), más la concatenación del valor de getQuery (), si corresponde. Si no hay una parte de la consulta, este método y getPath () devolverán resultados idénticos.)
sfussenegger
getPath()No use getFile().
Jason C