Как получить последний сегмент пути URI

114

У меня на входе строка с расширением URI. как можно получить последний сегмент пути (в моем случае это идентификатор)?

Это мой входной URL:

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

и мне нужно получить идентификатор, который я пробовал с этим:

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

но это не работает, и, безусловно, должен быть лучший способ сделать это.

DX89B
источник

Ответы:

174

это то, что вы ищете:

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

альтернативно

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
источник
49
Я искал android.net.Uri для Android (а не java.net.URI) и оказался здесь. Если вы используете это вместо этого, там есть метод getLastPathSegment (), который должен делать то же самое. :)
pm_labs 04
5
Просто сделайте то String idStr = new File(uri.getPath()).getName()же, что и этот ответ, но Fileвместо Stringразделения пути.
Jason C
это не будет работать для URL-адресов, таких как example.com/job/senior-health-and-nutrition-advisor/?param=true . Последний "/" создает проблемы. Нужно что-то более хорошее, ответ getLastPathSegment (), данный @paul_sns, идеален.
Vaibhav Kadam
@VaibhavKadam ну, технически вы можете возразить, что последний сегмент - это пустая строка. Но если это не то, что вы хотите, просто используйте:while (path.endsWith("/")) path = path.substring(0, path.length() - 1);
sfussenegger
@sfussenegger Плохо, что я не читал указанные теги. Я думал, что это тег android. Ну +1 для android.net.uri. :). Android берет на себя JAVA.
Vaibhav Kadam
69
import android.net.Uri;
Uri uri = Uri.parse("http://example.com/foo/bar/42?param=true");
String token = uri.getLastPathSegment();
Боковой
источник
1
Это "android.net.Uri"? Основа на тегах вопроса, предполагается, что java.net.URI и у него нет getLastPathSegment () ...
Майкл Гейзер
Кроме того, Uriимя класса Android записано в нижнем регистре и не может быть создано. Я исправил ваш ответ, чтобы использовать метод статической фабрики Uri.parse().
quietmint
GetLastPathSegment здесь не существует.
Абдулла Шоаиб
2
у него есть getLastPathSegment (), но он не работает! возвращает ноль!
Junia Montana
Похоже, что getLastPathSegment () случайным образом выдает мне полный путь.
MobDev
48

Вот краткий способ сделать это:

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

Код теста:

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

Вывод:

42
фу
бар

Объяснение:

.*/      // 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
Шон Патрик Флойд
источник
Хотя я большой поклонник регулярных выражений и сам часто использую их, я признаю, что для большинства разработчиков регулярное выражение настолько же тупо, насколько и получается. он не проще в том, что его не сразу понимают.
Билл Тернер,
В /инвертированном классе символов нет [^/?]необходимости, потому что он никогда не будет сопоставлен. .*/всегда будет соответствовать последнему / в строке, поэтому никаких других /встречаться не должно.
Стефан ван ден Аккер
не работает для такой ссылки. http://example.com/foo#reply2Было бы здорово, если бы вы могли обновить свой ответ, чтобы решить эту проблему. Спасибо
Сет
23

Я знаю, что это устарело, но решения здесь кажутся довольно многословными. Просто легко читаемый однострочник, если у вас есть URLили URI:

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

Или если у вас есть String:

String filename = new File(new URL(url).getPath()).getName();
Джейсон С
источник
Работает ли он со всеми возможными вариантами URL, например a.co/last?a=1#frag. Я думаю , что нет, так как код не делает подстроки последнего символа пути до конца: path.substring(index + 1).
AlikElzin-kilaka
4
@alik Вопрос касается последнего сегмента пути. Запрос и фрагмент не являются частью сегмента пути.
Jason C
13

Если вы используете Java 8 и вам нужен последний сегмент в пути к файлу, вы можете это сделать.

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

Если у вас есть URL-адрес, http://base_path/some_segment/idто можно сделать.

final Path urlPath = Paths.get("http://base_path/some_segment/id");
final Path lastSegment = urlPath.getName(urlPath.getNameCount() - 1);
Уилл Хамфрис
источник
4
Рискованно, потому что java.nio.file.Paths # get зависит от файловой системы ОС, в которой работает JVM. Нет гарантии, что он распознает URI с косой чертой в качестве разделителей пути.
Адриан Бейкер
2
А как насчет URI с параметрами запроса? Обработка случайного URI как пути к файловой системе требует исключения.
Abhijit Sarkar
9

В Android

В Android есть встроенный класс для управления URI.

Uri uri = Uri.parse("http://base_path/some_segment/id");
String lastPathSegment = uri.getLastPathSegment()
Брилл Паппин
источник
Иногда это просто выплевывает полный путь. Не знаю, почему и когда это кажется случайным.
MobDev
Если вы можете поймать анализируемый контент, возможно, вы можете настроить модульный тест, чтобы убедиться в этом.
Брилл Паппин,
8

В Java 7+ несколько предыдущих ответов можно объединить, чтобы разрешить получение любого сегмента пути из URI, а не только последнего сегмента. Мы можем преобразовать URI в java.nio.file.Pathобъект, чтобы воспользоваться его getName(int)методом.

К сожалению, статическая фабрика Paths.get(uri)не построена для обработки схемы http, поэтому нам сначала нужно отделить схему от пути 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();

Чтобы получить последний сегмент в одной строке кода, просто вложите строки выше.

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

Чтобы получить предпоследний сегмент, избегая при этом номеров индексов и потенциальных ошибок, не связанных друг с другом, используйте этот getParent()метод.

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

Обратите внимание, что getParent()метод можно вызывать повторно для получения сегментов в обратном порядке. В этом примере путь содержит только два сегмента, иначе при вызове getParent().getParent()будет извлечен предпоследний сегмент.

jaco0646
источник
6

Если вы commons-ioвключили в свой проект, вы можете сделать это без создания ненужных объектов с помощьюorg.apache.commons.io.FilenameUtils

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

Дам вам последнюю часть пути, то есть id

Bnrdo
источник
3

Вы можете использовать getPathSegments()функцию. ( Документация для Android )

Рассмотрим свой пример URI:

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

Вы можете получить последний сегмент, используя:

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

lastSegmentбудет id.

Сина Маснади
источник
1

Вы также можете использовать replaceAll:

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

System.out.println(lastSegment);

результат:

id
Кшиштоф Цихоцкий
источник
0

В служебном классе я использую следующее:

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();
}
Джеральд Брозер
источник
-1

Получите URL-адрес из URI и используйте getFile (), если вы не готовы использовать подстроку для извлечения файла.

Нагешвара Рао
источник
2
не будет работать, см. javadoc getFile (): получает имя файла по этому URL-адресу. Возвращенная часть файла будет такой же, как getPath (), плюс конкатенация значения getQuery (), если таковая имеется. Если части запроса нет, этот метод и getPath () вернут идентичные результаты.)
sfussenegger,
Используйте getPath()не getFile().
Jason C