2016-12-06 37 views
0

請參閱下面的Java代碼:關於URI相對化

URL u = new URL("http://www.site1.com/aaa/"); 
URL u2 = new URL("http://www.site1.com/aaa/ccc/aaa/"); 
URI r = u2.toURI().relativize(u.toURI()); 
System.out.println(r); // print: http://www.site1.com/aaa/ 

然而,如何返回真正的相對路徑:../../?

+1

什麼是預期的輸出? – GurV

+0

@Gurwinder,因爲r是相對路徑,我預計r是../../,因爲URI r = u.toURI()。relativize(u2.toURI());請注意:u.relative(u2),它可以得到正確的結果,但是,如果u2.relative(u)不能獲得相對路徑。 – chenzero

回答

0

你可能想切換u2u,因爲u前綴u2,像這樣:

URI r = u.toURI().relativize(u2.toURI()); 
System.out.println(r); // print: ccc/aaa/ 

根據URI.relativize() javadoc

定URI對的相對化該URI計算如下:如下:

  1. 如果任一此URI或給定URI是不透明的,或者如果兩個URI的方案和權威組分是不相同的,或者如果 URI的 路徑不是的路徑的前綴給定 URI,然後 給定URI返回

  2. 否則新相對分層URI構造有從給定的URI,並與通過從 給定URI的路徑開頭去除此URI的路徑計算的路徑 組件中取出,查詢和片段組件。

+0

謝謝。目前,我正在寫一個工具來重寫html中的url。我希望URL是相對的(以避免目錄改變絕對路徑的問題)。我知道u.relativize(u2)可以得到正確的相對路徑,但是仍然有可能遇到像u2.relativize(u)這樣的情況。似乎必須寫一些自定義的代碼來實現這一點......我會在這裏發佈一些...... – chenzero

+0

@chenzero我想你可以用'u2.startsWith(u)'(反之亦然)輕鬆地檢查一下。 – radoh

+0

u2.startsWith u)是整個功能的一個步驟,因爲我需要得到相對路徑,不管u2在你之下還是u2在你之前。 – chenzero

0

代碼,希望這是有用的:)

/** 
* split path 
* the String.split() is a little ambiguous because it might return empty string in the returned array that is unexpected. 
* in this function, the only case that returned array is empty is when path is/
* @param path 
* @return 
*/ 
public static String[] splitPath(String path) { 
    ArrayList<String> ret = new ArrayList<String>(); 
    Pattern p = Pattern.compile("/+"); 
    Matcher m = p.matcher(path); 
    int s0 = 0; 
    int s1,e1; 
    while(m.find()) { 
     s1 = m.start(); 
     e1 = m.end(); 
     if(s1-s0>0) { 
      ret.add(path.substring(s0,s1)); 
     } 
     s0 = e1; 
    } 
    if(s0<path.length()) { 
     ret.add(path.substring(s0)); 
    } 
    String[] a = ret.toArray(new String[0]); 
    return a; 
} 

/** 
* get the relative path against the base dir. 
* @param base - the base path, must be a directory. 
* @param path - the path to visit, can be directory or file. 
* @return - the relative path from base to the path. 
*/ 
public static String relativize(String baseDir, String path) { 
    if(!baseDir.endsWith("/")) { 
     baseDir = baseDir + "/"; // assume the baseDir is always a directory. 
    } 
    String[] bases = splitPath(baseDir); 
    String[] paths = splitPath(path); 
    int p = 0, q = 0; 

    while(p<bases.length && q<paths.length && bases[p].equals(paths[q])) { 
     p++; 
     q++; 
    } 

    StringBuilder sb = new StringBuilder(255); 
    int i; 
    for(i=bases.length-1;i>=p;i--) { 
     sb.append("../"); 
    } 

    for(i=q;i<paths.length;i++) { 
     sb.append(paths[i]); 
     if(i!=paths.length-1) { 
      sb.append("/"); 
     } 
    } 

    if(path.endsWith("/")) { 
     // ensure the last char of sb is not/
     i = sb.length(); 
     if(i>0 && sb.charAt(i-1)!='/') { 
      sb.append("/"); 
     } 
    } 
    return sb.toString(); 
} 

static void testRelativize() { 
    String r; 
    r = relativize("/", "/acdde"); 
    if(!"acdde".equals(r)) { 
     throw new RuntimeException("1"); 
    } 

    r = relativize("/a", "/b/c"); 
    if(!"../b/c".equals(r)) { 
     throw new RuntimeException("2"); 
    } 

    r = relativize("/c", "/c/a/"); 
    if(!"a/".equals(r)) { 
     throw new RuntimeException("3"); 
    } 

    r = relativize("/c/d", "/c/a/a.txt"); 
    if(!"../a/a.txt".equals(r)) { 
     throw new RuntimeException("4"); 
    } 

    r = relativize("/c/b/d/", "/c/"); 
    if(!"../../".equals(r)) { 
     throw new RuntimeException("5"); 
    } 

    r = relativize("/c/d", "/c/d/a.txt"); 
    if(!"a.txt".equals(r)) { 
     throw new RuntimeException("6"); 
    } 
}