代碼,希望這是有用的:)
/**
* 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");
}
}
什麼是預期的輸出? – GurV
@Gurwinder,因爲r是相對路徑,我預計r是../../,因爲URI r = u.toURI()。relativize(u2.toURI());請注意:u.relative(u2),它可以得到正確的結果,但是,如果u2.relative(u)不能獲得相對路徑。 – chenzero