Here you can find the source of getRelativePath(File parent, File f)
public static String getRelativePath(File parent, File f)
//package com.java2s; /*/*w w w.j a v a 2s .c o m*/ * Unitex * * Copyright (C) 2001-2016 Universit? Paris-Est Marne-la-Vall?e <unitex@univ-mlv.fr> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * */ import java.io.File; public class Main { /** * Creates a description of f relative to parent. For instance: * * parent=/tmp/grf/toto.grf file=/tmp/grf/sub/foo.grf => sub/foo.grf * * parent=/tmp/grf/toto.grf file=/dst/foo.grf => ../../dst/foo.grf */ public static String getRelativePath(File parent, File f) { File dir; if (parent.isDirectory()) { dir = parent; } else { dir = parent.getParentFile(); } String s = isAncestor(dir, f.getParentFile()); if (s != null) { /* Case 1: f is in the same dir or a child dir */ return s + f.getName(); } /* Case 2: we have to find the common dir ancestor */ final File ancestor = commonAncestor(dir, f.getParentFile()); if (ancestor == null) { /* * If files are on different drives under Windows, we have no * choice: we must use f's absolute path */ return f.getAbsolutePath(); } s = f.getName(); f = f.getParentFile(); while (!f.equals(ancestor)) { s = f.getName() + File.separator + s; f = f.getParentFile(); } final int n = dirsUpToDir(ancestor, parent); for (int i = 0; i < n; i++) s = ".." + File.separator + s; return s; } /** * Return a non null relative path if dir1 is equals to dir2 or is an * ancestor of dir2 */ public static String isAncestor(File dir1, File dir2) { String s = ""; while (dir2 != null && !dir2.equals(dir1)) { s = dir2.getName() + File.separator + s; dir2 = dir2.getParentFile(); } if (dir2 != null) return s; return null; } /** * Returns the common directory ancestor, or null if there is none because * the files are on different drives under Windows. */ private static File commonAncestor(File dir1, File dir2) { int n1 = dirsUpToRoot(dir1); final int n2 = dirsUpToRoot(dir2); if (n1 < n2) { dir2 = moveUp(n2 - n1, dir2); } else if (n1 > n2) { dir1 = moveUp(n1 - n2, dir1); } /* At this point, we have dir1 and dir2 at the same depth from the root */ while (n1 >= 0) { if (dir1.equals(dir2)) { return dir1; } n1--; dir1 = dir1.getParentFile(); dir2 = dir2.getParentFile(); } /* If we get there, we are in a Windows case like dir1=C:\ and dir2=D:\ */ return null; } /** * Returns the number of directories there are to cross up before reaching * the parent directory: * * /tmp/sub/ /tmp/sub/titi/tata/toto/ => 2 */ private static int dirsUpToDir(File parent, File dir) { int n = 0; while (!dir.equals(parent)) { n++; dir = dir.getParentFile(); } return n; } /** * Returns the number of directories there are to cross up before reaching * the root: * * /tmp/sub/ => 2 */ private static int dirsUpToRoot(File dir) { int n = 0; while (!isRoot(dir)) { n++; dir = dir.getParentFile(); } return n; } /** * Performs n 'cd ..' on the given directory */ private static File moveUp(int n, File dir) { while (n != 0) { n--; dir = dir.getParentFile(); } return dir; } private static boolean isRoot(File dir) { for (final File f : File.listRoots()) { if (f.equals(dir)) return true; } return false; } }