如何获取URI的最后路径段

140

我有一个输入字符串,其中包含一个URI。如何获取最后一段路径(在我的情况下是一个id)?

这是我的输入网址:

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

我需要获取id,我已经尝试过以下方法:

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

但是它不起作用,肯定会有更好的方法来实现它。


方法 getLastPathSegment 在安卓6.0中无法处理带有 : 的情况。 - Roman Soviak
14个回答

215

这是你正在寻找的吗:

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

58
我在寻找Android的android.net.Uri(不是java.net.URI),结果来到了这里。如果你正在使用它,那么有一个叫做getLastPathSegment()的方法,它应该可以做同样的事情。 :) - pm_labs
5
只需执行String idStr = new File(uri.getPath()).getName(),与此答案相同,但使用File代替String来分割路径。 - Jason C
这段程序相关的内容翻译成中文如下:对于像 http://example.com/job/senior-health-and-nutrition-advisor/?param=true 这样的 URL 无法正常工作,最后的“/”会出现问题。需要更好的解决办法。@paul_sns 提供的 getLastPathSegment() 答案非常完美。 - Vaibhav Kadam
@VaibhavKadam 嗯,从技术上讲,你可以说最后一节是一个空字符串。但如果这不是你想要的,只需使用:while (path.endsWith("/")) path = path.substring(0, path.length() - 1); - sfussenegger
@sfussenegger 对不起,我没有在问题中阅读标签。我以为它有android的标签。好吧,+1给android.net.uri。:)Android正在接管JAVA。 - Vaibhav Kadam
用它来提取SQS队列名称。原生实现没有简单的方法来做到这一点。它只返回队列URL。 - Shtefan

82
import android.net.Uri;
Uri uri = Uri.parse("http://example.com/foo/bar/42?param=true");
String token = uri.getLastPathSegment();

2
这是“android.net.Uri”吗?根据问题的标签,应该假定为java.net.URI,但它没有getLastPathSegment()... - Michael Geiser
此外,Android 的 Uri 类名是小写的,不能被实例化。我已经更正了你的答案,使用了静态工厂方法 Uri.parse() - quietmint
这里不存在 GetLastPathSegment。 - Abdullah Shoaib
2
它确实有getLastPathSegment(),但它不起作用!返回null! - Junia Montana
看起来 getLastPathSegment() 会随机给我返回完整的路径。 - MobDev
@MobDev 你能提供一些例子吗? - Vadim Kotov

55

这是一个简短的方法:

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
foo
bar

解释:

.*/      // 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

虽然我是正则表达式的忠实粉丝并经常使用它,但我认识到对于大多数开发人员来说,正则表达式就像晦涩难懂的东西一样。它并不简单,因为它不能被迅速理解。 - Bill Turner
在否定字符类[^/?]中的/是不必要的,因为它永远不会被匹配。.*/将始终匹配字符串中的最后一个/,因此不应遇到其他/ - Stefan van den Akker
1
对于这种链接“http://example.com/foo#reply2”,该方法无效。如果您能更新您的答案来解决这个问题,那就太好了。谢谢。 - Seth
@Seth,我刚刚尝试了一下;如果你将正则表达式更新为([^#/?]+)而不是([^/?]+),那应该可以工作。 - Ronald Wolvers

29

我知道这很老了,但这里的解决方案似乎有点啰嗦。如果你有一个URLURI,这是一个易于阅读的一行代码:

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
问题要求获取路径的最后一段。查询和片段不属于路径段。 - Jason C

16

如果您使用的是Java 8,并且希望获取文件路径中的最后一个段落,可以执行以下操作:

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

如果您有一个像 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);

10
这段内容的意思是:使用java.nio.file.Paths#get方法存在风险,因为该方法依赖于JVM运行的操作系统文件系统。无法保证它能够识别斜杠作为路径分隔符的URI。 - Adrian Baker
3
URI带有查询参数怎么办?把任意URI当作文件系统路径来处理会引发异常。 - Abhijit Sarkar

15

在Android中

Android内置了一个管理统一资源标识符(URI)的类。

Uri uri = Uri.parse("http://base_path/some_segment/id");
String lastPathSegment = uri.getLastPathSegment()

有时它只会输出完整路径。不确定为什么或何时似乎是随机的。 - MobDev
如果您能捕获它正在解析的内容,也许您可以设置一个单元测试来确保。 - Brill Pappin

11
如果您的项目中包含了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


7
你也可以使用replaceAll:
String uri = "http://base_path/some_segment/id"
String lastSegment = uri.replaceAll(".*/", "")

System.out.println(lastSegment);

结果:

id

7
在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() 将会检索到倒数第三个段落。

5
你可以使用 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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接