给出两条绝对路径,例如

/var/data/stuff/xyz.dat
/var/data

如何创建一个以第二条路径为基础的相对路径?在上面的例子中,结果应该是:./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以来,路径#相对化。

其他回答

这有点迂回,但为什么不使用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以来,路径#相对化。

这里已经有很多答案了,但我发现他们并不能处理所有的情况,比如基地和目标是相同的。这个函数接受一个基本目录和一个目标路径,并返回相对路径。如果不存在相对路径,则返回目标路径。文件。分隔符是不必要的。

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

ant有一个带有getRelativePath方法的FileUtils类。我自己还没有尝试过,但是值得一试。

http://javadoc.haefelinger.it/org.apache.ant/1.7.1/org/apache/tools/ant/util/FileUtils.html getRelativePath (java.io.File java.io.File)

Psuedo-code:

使用路径分隔符("/")拆分字符串 通过迭代拆分字符串的结果来找到最大的公共路径(因此在两个示例中,您最终会得到"/var/data"或"/a") 返回“。”+ whicheverPathIsLonger.substring (commonPath.length);

当使用java.net.URI.relativize时,你应该注意Java错误: JDK-6226081 (URI应该能够将路径与部分根相对化)

目前,URI的relativize()方法只在一个URI是另一个URI的前缀时才会相对化URI。

这本质上意味着java.net.URI.relativize将不会创建“…这是给你的。