给出两条绝对路径,例如

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

如何创建一个以第二条路径为基础的相对路径?在上面的例子中,结果应该是:./stuff/xyz.dat


当前回答

Psuedo-code:

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

其他回答

下面是一个从基本路径解析相对路径的方法,不管它们在相同或不同的根路径中:

public static String GetRelativePath(String path, String base){

    final String SEP = "/";

    // if base is not a directory -> return empty
    if (!base.endsWith(SEP)){
        return "";
    }

    // check if path is a file -> remove last "/" at the end of the method
    boolean isfile = !path.endsWith(SEP);

    // get URIs and split them by using the separator
    String a = "";
    String b = "";
    try {
        a = new File(base).getCanonicalFile().toURI().getPath();
        b = new File(path).getCanonicalFile().toURI().getPath();
    } catch (IOException e) {
        e.printStackTrace();
    }
    String[] basePaths = a.split(SEP);
    String[] otherPaths = b.split(SEP);

    // check common part
    int n = 0;
    for(; n < basePaths.length && n < otherPaths.length; n ++)
    {
        if( basePaths[n].equals(otherPaths[n]) == false )
            break;
    }

    // compose the new path
    StringBuffer tmp = new StringBuffer("");
    for(int m = n; m < basePaths.length; m ++)
        tmp.append(".."+SEP);
    for(int m = n; m < otherPaths.length; m ++)
    {
        tmp.append(otherPaths[m]);
        tmp.append(SEP);
    }

    // get path string
    String result = tmp.toString();

    // remove last "/" if path is a file
    if (isfile && result.endsWith(SEP)){
        result = result.substring(0,result.length()-1);
    }

    return result;
}

如果你知道第二个字符串是第一个字符串的一部分:

String s1 = "/var/data/stuff/xyz.dat";
String s2 = "/var/data";
String s3 = s1.substring(s2.length());

或者,如果你真的想把句号放在开头,就像你的例子中那样:

String s3 = ".".concat(s1.substring(s2.length()));

我的版本大致基于马特和史蒂夫的版本:

/**
 * Returns the path of one File relative to another.
 *
 * @param target the target directory
 * @param base the base directory
 * @return target's path relative to the base directory
 * @throws IOException if an error occurs while resolving the files' canonical names
 */
 public static File getRelativeFile(File target, File base) throws IOException
 {
   String[] baseComponents = base.getCanonicalPath().split(Pattern.quote(File.separator));
   String[] targetComponents = target.getCanonicalPath().split(Pattern.quote(File.separator));

   // skip common components
   int index = 0;
   for (; index < targetComponents.length && index < baseComponents.length; ++index)
   {
     if (!targetComponents[index].equals(baseComponents[index]))
       break;
   }

   StringBuilder result = new StringBuilder();
   if (index != baseComponents.length)
   {
     // backtrack to base directory
     for (int i = index; i < baseComponents.length; ++i)
       result.append(".." + File.separator);
   }
   for (; index < targetComponents.length; ++index)
     result.append(targetComponents[index] + File.separator);
   if (!target.getPath().endsWith("/") && !target.getPath().endsWith("\\"))
   {
     // remove final path separator
     result.delete(result.length() - File.separator.length(), result.length());
   }
   return new File(result.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();
}

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

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

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