Skip to content

Instantly share code, notes, and snippets.

@zaki50
Created June 16, 2012 08:09
Show Gist options
  • Save zaki50/2940460 to your computer and use it in GitHub Desktop.
Save zaki50/2940460 to your computer and use it in GitHub Desktop.
Compute relative path from a directory to other file or directory. a derivative of https://gist.github.com/2940215
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class RelativePath {
public static String relativePath(String origin, String target) {
try {
origin = (new File(origin)).getCanonicalPath();
target = (new File(target)).getCanonicalPath();
} catch (IOException e) {
return null;
}
if (System.getProperty("os.name").indexOf("Windows") != -1) {
if (origin.startsWith("\\\\") || target.startsWith("\\\\")) {
// Windows UNC path not supported.
return null;
}
char originLetter = origin.charAt(0);
char targetLetter = target.charAt(0);
if (Character.isLetter(originLetter)
&& Character.isLetter(targetLetter)) {
// Windows only
if (originLetter != targetLetter) {
// Drive letters differ
return null;
}
}
}
final String[] originArray = splitBySeparator(origin);
final String[] targetArray = splitBySeparator(target);
final int maxCommonComponents = Math.min(originArray.length,
targetArray.length);
int commonComponents = 0;
while (commonComponents < maxCommonComponents
&& originArray[commonComponents]
.equals(targetArray[commonComponents])) {
commonComponents++;
}
final int ancestors = originArray.length - commonComponents;
final int descendant = targetArray.length - commonComponents;
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < ancestors; i++) {
sb.append("..").append(File.separator);
}
for (int i = 0; i < descendant; i++) {
sb.append(targetArray[commonComponents + i]).append(File.separator);
}
if (sb.length() != 0) {
sb.setLength(sb.length() - File.separator.length());
}
if (sb.length() == 0) {
return ".";
}
return sb.toString();
}
private static String[] splitBySeparator(String path) {
final StringTokenizer tk = new StringTokenizer(path, File.separator,
false);
final List<String> components = new ArrayList<String>();
while (tk.hasMoreTokens()) {
components.add(tk.nextToken());
}
return components.toArray(new String[components.size()]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment