Como obter o último segmento de caminho de um URI

114

Eu tenho como entrada uma string que é um URI . como é possível obter o último segmento de caminho (que no meu caso é um id)?

Este é o meu URL de entrada:

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

e eu tenho que obter o id que tentei com isso:

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

mas não funciona, e certamente deve haver uma maneira melhor de fazer isso.

DX89B
fonte

Respostas:

174

é isso que você está procurando:

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
fonte
49
Eu estava procurando por android.net.Uri do Android (não java.net.URI) e acabei aqui. Se você estiver usando isso, há um método chamado getLastPathSegment () que deve fazer a mesma coisa. :)
pm_labs
5
Basta fazer o String idStr = new File(uri.getPath()).getName()mesmo que esta resposta, mas usa em Filevez de Stringpara dividir o caminho.
Jason C
isso não funcionará para urls como example.com/job/senior-health-and-nutrition-advisor/?param=true . O último "/" está causando problemas. Precisa de algo mais. A resposta getLastPathSegment () dada por @paul_sns é perfeita.
Vaibhav Kadam
@VaibhavKadam bem, tecnicamente você poderia argumentar que o último segmento é uma string vazia. Mas se não for isso que você deseja, basta usar:while (path.endsWith("/")) path = path.substring(0, path.length() - 1);
sfussenegger
@sfussenegger Meu mal, não li os TAGs em questão. Achei que tivesse tag de android. Bem, +1 para android.net.uri. :). O Android está assumindo o controle 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
fonte
1
É "android.net.Uri"? Com base nas tags da pergunta, java.net.URI seria assumido e não tem getLastPathSegment () ...
Michael Geiser
Além disso, o Urinome da classe Android está em minúsculas e não pode ser instanciado. Corrigi sua resposta para usar o método de fábrica estático Uri.parse().
quietmint de
GetLastPathSegment não existe aqui.
Abdullah Shoaib
2
tem getLastPathSegment (), mas não funciona! retorna nulo!
Junia Montana
Parece que getLastPathSegment () mostra aleatoriamente o caminho completo para mim.
MobDev
48

Aqui está um método curto para fazer isso:

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

Código de teste:

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

Resultado:

42
foo
bar

Explicação:

.*/      // 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
fonte
embora eu seja um grande fã de regex e o use com frequência, reconheço que, para a maioria dos desenvolvedores, regex é o mais obtuso que pode existir. não é mais simples no fato de que não é compreendido rapidamente.
Bill Turner
O /na classe de caractere negado [^/?]é desnecessário, porque nunca será correspondido. .*/sempre corresponderá ao último / na String, portanto, nenhum outro /deve ser encontrado.
Stefan van den Akker
não funciona para este tipo de link http://example.com/foo#reply2, seria ótimo se você pudesse atualizar sua resposta para resolvê-lo. Obrigado
Seth
23

Eu sei que isso é antigo, mas as soluções aqui parecem bastante prolixas. Apenas uma linha de fácil leitura se você tiver um URLou URI:

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

Ou se você tiver um String:

String filename = new File(new URL(url).getPath()).getName();
Jason C
fonte
Funciona com todas as opções possíveis de um URL, como a.co/last?a=1#frag. Acho que não, que o código não substring do último símbolo caminho até o fim: path.substring(index + 1).
AlikElzin-kilaka de
4
@alik A questão pede o último segmento do caminho. A consulta e o fragmento não fazem parte do segmento do caminho.
Jason C
13

Se você estiver usando Java 8 e quiser o último segmento em um caminho de arquivo, pode fazer.

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

Se você tiver um url como http://base_path/some_segment/idvocê pode fazer.

final Path urlPath = Paths.get("http://base_path/some_segment/id");
final Path lastSegment = urlPath.getName(urlPath.getNameCount() - 1);
Will Humphreys
fonte
4
Arriscado porque java.nio.file.Paths # get depende do sistema de arquivos do SO no qual a JVM está sendo executada. Não há garantia de que ele reconhecerá um URI com barras como separadores de caminho.
Adrian Baker
2
E quanto ao URI com parâmetros de consulta? Tratar um URI aleatório como um caminho do sistema de arquivos é pedir uma exceção.
Abhijit Sarkar
9

No Android

O Android tem uma classe integrada para gerenciar URIs.

Uri uri = Uri.parse("http://base_path/some_segment/id");
String lastPathSegment = uri.getLastPathSegment()
Brill Pappin
fonte
Às vezes, isso apenas mostra o caminho completo. Não sei por que ou quando parece ser aleatório.
MobDev
Se você pode pegar o conteúdo que está analisando, talvez você possa configurar um teste de unidade para ter certeza.
Brill Pappin
8

Em Java 7 ou superior, algumas das respostas anteriores podem ser combinadas para permitir a recuperação de qualquer segmento de caminho de um URI, em vez de apenas o último segmento. Podemos converter o URI em um java.nio.file.Pathobjeto, para tirar proveito de suagetName(int) método.

Infelizmente, a fábrica estática Paths.get(uri)não foi construída para lidar com o esquema http, portanto, primeiro precisamos separar o esquema do caminho do 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 obter o último segmento em uma linha de código, simplesmente aninhe as linhas acima.

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

Para obter o penúltimo segmento e, ao mesmo tempo, evitar números de índice e o potencial de erros defasados, use o getParent()método.

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

Observe que o getParent()método pode ser chamado repetidamente para recuperar segmentos na ordem inversa. Neste exemplo, o caminho contém apenas dois segmentos, caso contrário, a chamada getParent().getParent()recuperaria o terceiro ao último segmento.

jaco0646
fonte
6

Se você commons-ioincluiu em seu projeto, você pode fazê-lo sem criar objetos desnecessários comorg.apache.commons.io.FilenameUtils

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

Irá lhe dar a última parte do caminho, que é o id

Bnrdo
fonte
3

Você pode usar a getPathSegments()função. ( Documentação Android )

Considere seu URI de exemplo:

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

Você pode obter o último segmento usando:

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

lastSegmentserá id.

Sina Masnadi
fonte
1

Você também pode usar replaceAll:

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

System.out.println(lastSegment);

resultado:

id
Krzysztof Cichocki
fonte
0

Estou usando o seguinte em uma classe de utilitário:

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

Obtenha a URL do URI e use getFile () se você não estiver pronto para usar a forma de substring de extrair o arquivo.

Nageswara Rao
fonte
2
não funcionará, consulte javadoc de getFile (): Obtém o nome do arquivo desta URL. A parte do arquivo retornado será igual a getPath (), mais a concatenação do valor de getQuery (), se houver. Se não houver parte da consulta, este método e getPath () retornarão resultados idênticos.)
sfussenegger
getPath()Não use getFile().
Jason C