给出两条绝对路径,例如
/var/data/stuff/xyz.dat
/var/data
如何创建一个以第二条路径为基础的相对路径?在上面的例子中,结果应该是:./stuff/xyz.dat
给出两条绝对路径,例如
/var/data/stuff/xyz.dat
/var/data
如何创建一个以第二条路径为基础的相对路径?在上面的例子中,结果应该是:./stuff/xyz.dat
当前回答
我知道这有点晚了,但是,我创建了一个解决方案,适用于任何java版本。
public static String getRealtivePath(File root, File file)
{
String path = file.getPath();
String rootPath = root.getPath();
boolean plus1 = path.contains(File.separator);
return path.substring(path.indexOf(rootPath) + rootPath.length() + (plus1 ? 1 : 0));
}
其他回答
我假设你有fromPath(一个文件夹的绝对路径),和toPath(一个文件夹/文件的绝对路径),你正在寻找一个路径,代表文件/文件夹在toPath作为一个相对路径从fromPath(你当前的工作目录是fromPath),然后像这样的工作:
public static String getRelativePath(String fromPath, String toPath) {
// This weirdness is because a separator of '/' messes with String.split()
String regexCharacter = File.separator;
if (File.separatorChar == '\\') {
regexCharacter = "\\\\";
}
String[] fromSplit = fromPath.split(regexCharacter);
String[] toSplit = toPath.split(regexCharacter);
// Find the common path
int common = 0;
while (fromSplit[common].equals(toSplit[common])) {
common++;
}
StringBuffer result = new StringBuffer(".");
// Work your way up the FROM path to common ground
for (int i = common; i < fromSplit.length; i++) {
result.append(File.separatorChar).append("..");
}
// Work your way down the TO path
for (int i = common; i < toSplit.length; i++) {
result.append(File.separatorChar).append(toSplit[i]);
}
return result.toString();
}
private String relative(String left, String right){
String[] lefts = left.split("/");
String[] rights = right.split("/");
int min = Math.min(lefts.length, rights.length);
int commonIdx = -1;
for(int i = 0; i < min; i++){
if(commonIdx < 0 && !lefts[i].equals(rights[i])){
commonIdx = i - 1;
break;
}
}
if(commonIdx < 0){
return null;
}
StringBuilder sb = new StringBuilder(Math.max(left.length(), right.length()));
sb.append(left).append("/");
for(int i = commonIdx + 1; i < lefts.length;i++){
sb.append("../");
}
for(int i = commonIdx + 1; i < rights.length;i++){
sb.append(rights[i]).append("/");
}
return sb.deleteCharAt(sb.length() -1).toString();
}
当使用java.net.URI.relativize时,你应该注意Java错误: JDK-6226081 (URI应该能够将路径与部分根相对化)
目前,URI的relativize()方法只在一个URI是另一个URI的前缀时才会相对化URI。
这本质上意味着java.net.URI.relativize将不会创建“…这是给你的。
这里有一个其他库免费的解决方案:
Path sourceFile = Paths.get("some/common/path/example/a/b/c/f1.txt");
Path targetFile = Paths.get("some/common/path/example/d/e/f2.txt");
Path relativePath = sourceFile.relativize(targetFile);
System.out.println(relativePath);
输出
..\..\..\..\d\e\f2.txt
[编辑]实际上它输出更多。因为源文件不是目录。对于我的情况,正确的解决方案是:
Path sourceFile = Paths.get(new File("some/common/path/example/a/b/c/f1.txt").parent());
Path targetFile = Paths.get("some/common/path/example/d/e/f2.txt");
Path relativePath = sourceFile.relativize(targetFile);
System.out.println(relativePath);
递归产生一个较小的解决方案。如果结果不可能(例如不同的Windows磁盘)或不切实际(根目录只是普通目录),则抛出异常。
/**
* Computes the path for a file relative to a given base, or fails if the only shared
* directory is the root and the absolute form is better.
*
* @param base File that is the base for the result
* @param name File to be "relativized"
* @return the relative name
* @throws IOException if files have no common sub-directories, i.e. at best share the
* root prefix "/" or "C:\"
*/
public static String getRelativePath(File base, File name) throws IOException {
File parent = base.getParentFile();
if (parent == null) {
throw new IOException("No common directory");
}
String bpath = base.getCanonicalPath();
String fpath = name.getCanonicalPath();
if (fpath.startsWith(bpath)) {
return fpath.substring(bpath.length() + 1);
} else {
return (".." + File.separator + getRelativePath(parent, name));
}
}