给出两条绝对路径,例如
/var/data/stuff/xyz.dat
/var/data
如何创建一个以第二条路径为基础的相对路径?在上面的例子中,结果应该是:./stuff/xyz.dat
给出两条绝对路径,例如
/var/data/stuff/xyz.dat
/var/data
如何创建一个以第二条路径为基础的相对路径?在上面的例子中,结果应该是:./stuff/xyz.dat
当前回答
这里已经有很多答案了,但我发现他们并不能处理所有的情况,比如基地和目标是相同的。这个函数接受一个基本目录和一个目标路径,并返回相对路径。如果不存在相对路径,则返回目标路径。文件。分隔符是不必要的。
public static String getRelativePath (String baseDir, String targetPath) {
String[] base = baseDir.replace('\\', '/').split("\\/");
targetPath = targetPath.replace('\\', '/');
String[] target = targetPath.split("\\/");
// Count common elements and their length.
int commonCount = 0, commonLength = 0, maxCount = Math.min(target.length, base.length);
while (commonCount < maxCount) {
String targetElement = target[commonCount];
if (!targetElement.equals(base[commonCount])) break;
commonCount++;
commonLength += targetElement.length() + 1; // Directory name length plus slash.
}
if (commonCount == 0) return targetPath; // No common path element.
int targetLength = targetPath.length();
int dirsUp = base.length - commonCount;
StringBuffer relative = new StringBuffer(dirsUp * 3 + targetLength - commonLength + 1);
for (int i = 0; i < dirsUp; i++)
relative.append("../");
if (commonLength < targetLength) relative.append(targetPath.substring(commonLength));
return relative.toString();
}
其他回答
这里已经有很多答案了,但我发现他们并不能处理所有的情况,比如基地和目标是相同的。这个函数接受一个基本目录和一个目标路径,并返回相对路径。如果不存在相对路径,则返回目标路径。文件。分隔符是不必要的。
public static String getRelativePath (String baseDir, String targetPath) {
String[] base = baseDir.replace('\\', '/').split("\\/");
targetPath = targetPath.replace('\\', '/');
String[] target = targetPath.split("\\/");
// Count common elements and their length.
int commonCount = 0, commonLength = 0, maxCount = Math.min(target.length, base.length);
while (commonCount < maxCount) {
String targetElement = target[commonCount];
if (!targetElement.equals(base[commonCount])) break;
commonCount++;
commonLength += targetElement.length() + 1; // Directory name length plus slash.
}
if (commonCount == 0) return targetPath; // No common path element.
int targetLength = targetPath.length();
int dirsUp = base.length - commonCount;
StringBuffer relative = new StringBuffer(dirsUp * 3 + targetLength - commonLength + 1);
for (int i = 0; i < dirsUp; i++)
relative.append("../");
if (commonLength < targetLength) relative.append(targetPath.substring(commonLength));
return relative.toString();
}
我假设你有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();
}
这里有一个其他库免费的解决方案:
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);
从Java 7开始,你可以使用relativize方法:
import java.nio.file.Path;
import java.nio.file.Paths;
public class Test {
public static void main(String[] args) {
Path pathAbsolute = Paths.get("/var/data/stuff/xyz.dat");
Path pathBase = Paths.get("/var/data");
Path pathRelative = pathBase.relativize(pathAbsolute);
System.out.println(pathRelative);
}
}
输出:
stuff/xyz.dat
这有点迂回,但为什么不使用URI呢?它有一个相对化方法可以帮你做所有必要的检查。
String path = "/var/data/stuff/xyz.dat";
String base = "/var/data";
String relative = new File(base).toURI().relativize(new File(path).toURI()).getPath();
// relative == "stuff/xyz.dat"
请注意文件路径是java.nio.file。正如@Jirka Meluzin在另一个答案中指出的那样,自Java 1.7以来,路径#相对化。