Here you can find the source of getRelativePath(File source, File destination)
Parameter | Description |
---|---|
source | The source file or location |
destination | The file to target with the relative path |
public static String getRelativePath(File source, File destination) throws IOException
//package com.java2s; //License from project: Open Source License import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; public class Main { /**/*from w w w. j a v a 2 s .co m*/ * Gets a relative path from the source file to the destination * * @param source * The source file or location * @param destination * The file to target with the relative path * @return The relative path from the source file's directory to the * destination file */ public static String getRelativePath(File source, File destination) throws IOException { String sourceDir = null; String destDir = null; if (source.isDirectory()) { sourceDir = source.getCanonicalPath(); } else { sourceDir = source.getParentFile().getCanonicalPath(); } if (destination.isDirectory()) { destDir = destination.getCanonicalPath(); } else { destDir = destination.getParentFile().getCanonicalPath(); } // find the overlap in the source and dest paths String overlap = findOverlap(sourceDir, destDir); // strip off a training File.separator if (overlap.endsWith(File.separator)) { if (overlap.equals(File.separator)) { overlap = ""; } else { overlap = overlap.substring(0, overlap.length() - File.separator.length() - 1); } } int overlapDirs = countChars(overlap, File.separatorChar); if (overlapDirs == 0) { // no overlap at all, return full path of destination file return destination.getCanonicalPath(); } // difference is the number of path elements to back up before moving // down the tree int parentDirsNeeded = countChars(sourceDir, File.separatorChar) - overlapDirs; // difference is the number of path elements above the file to keep int parentDirsKept = countChars(destDir, File.separatorChar) - overlapDirs; // build the path StringBuffer relPath = new StringBuffer(); for (int i = 0; i < parentDirsNeeded; i++) { relPath.append("..").append(File.separatorChar); } List<String> parentPaths = new LinkedList<String>(); File parentDir = new File(destDir); for (int i = 0; i < parentDirsKept; i++) { parentPaths.add(parentDir.getName()); parentDir = parentDir.getParentFile(); } Collections.reverse(parentPaths); for (Iterator<String> i = parentPaths.iterator(); i.hasNext();) { relPath.append(i.next()).append(File.separatorChar); } if (!destination.isDirectory()) { relPath.append(destination.getName()); } return relPath.toString(); } private static String findOverlap(String s1, String s2) { // TODO: More efficient would be some kind of binary search, divide and // conquer StringBuffer overlap = new StringBuffer(); int count = Math.min(s1.length(), s2.length()); for (int i = 0; i < count; i++) { char c1 = s1.charAt(i); char c2 = s2.charAt(i); if (c1 == c2) { overlap.append(c1); } else { break; } } return overlap.toString(); } /** * Like Object.equals, but if o1 == null && o2 == null, returns true * * @param o1 * @param o2 * @return */ public static boolean equals(Object o1, Object o2) { if (o1 == null) { return o2 == null; } return o1.equals(o2); } private static int countChars(String s, char c) { int count = 0; int index = -1; while ((index = s.indexOf(c, index + 1)) != -1) { count++; } return count; } }