Find relative path from one URL to another in Java
给定两条路径,如何计算从一条到另一条的相对路径?
我曾想过用花哨的方式使用split,但它似乎有点黑客,特别是在像"http://foo.com/bar/baz#header"或"http://foo.com/bar/baz"?param=value这样的情况下。
例如:
1 2 3 4
| String url1 ="http://foo.com/bar/baz";
String url2 ="http://foo.com/bar/qux/quux/corge";
System. out. println(relative (url1, url2 )); // ->"../qux/quux/corge" |
- 你从url1到url2的相对路径不是./qux/quux/corge,而是../qux/quux/corge。
- @琼尼,你说得对。编辑我的帖子
- 相关:stackoverflow.com/a/705963/1831987
Java已经提供了这个功能,所以最安全的选择是采用"标准"方式:
1 2 3 4 5 6 7 8
| String url1 ="http://foo.com/bar/baz";
String url2 ="http://foo.com/bar/qux/quux/corge";
Path p1 = Paths. get(url1 );
Path p2 = Paths. get(url2 );
Path p = p1. relativize(p2 );
System. out. println("Relative path:" + p ); |
上面的print语句显示了正确的相对路径,在这种情况下,
如果协议(如http vs https)和主机部分可能不同,那么将上面的url1和url2转换成URLobjectsand using thegetpath()方法,应该产生正确的相对路径。
- 我测试过这个,为什么这个代码显示Illegal char <:> at index 4?
- 出于某种原因,我得到了java.nio.file.InvalidPathException: Illegal char <:> at index 4: http://foo.com/bar/baz。我用的是import java.nio.file.*;。
- @布莱恩,我发现你需要处理url1,url2来移除http:,然后relativize就可以工作了
- 我把Path p1 = Paths.get(url1);改成p1 = Paths.get(new URL(url1).getPath());,同一个top2,它起作用了。
- @Svasa,在我点击send之前,你一直在评论;)
- 它的工作原理和我在答案中发布的完全一样,在OracleJDK1.7forLinux中进行了测试。否则是的,合理的做法是布莱恩建议的。-)
- 这是错误的。URL不是路径。而url.getPath()绝对不会将url转换为有效的文件名。
- 到底怎么了?假设主机部分相同,则事件url.getPath()按预期工作。这是Paths.get()所假定的。
不管你用的是什么黑客方法,它都必须在引擎盖下循环访问你的URL。indexof()、split()和其他查找字符的函数仍然有O(n)运行时,因为它们需要查找这些字符。所以,您也可以编写自己的"indexof"样式函数。只需比较每个字符,一次一个,直到找到不同之处。这标志着相同URL的结束,并且由于我们可以在循环之外偷偷地声明"i",所以我们可以退出循环,并保留该索引。然后你只需把剩下的长网址吐出来!
1 2 3 4 5 6 7 8 9 10
| public String relative (String url1, String url2 ) {
int i ;
for(i = 0; i < url1. length(); i ++) {
if(url1. charAt(i ) != url2. charAt(i ))
break;
}
if(url1. length() > url2. length())
return url1. substring(i );
return url2. substring(i );
} |
- 这只在您首先使URL正常化时才有效。PathAPI方法要好得多。
你可以这样做:
1 2 3 4 5 6 7 8 9 10
| public static String relative (String url1, String url2 ){
String[] parts = url1. split("/");
String similar ="";
for(String part :parts ){
if(url2. contains(similar +part +"/")){
similar +=part +"/";
}
}
return"./"+url2. replace(similar, "");
} |
- 这只在您首先使URL正常化时才有效。PathAPI方法要好得多。
- @是的,我不知道。