Java Path Relative Get getRelativePath(File parent, File f)

Here you can find the source of getRelativePath(File parent, File f)

Description

Creates a description of f relative to parent.

License

Open Source License

Declaration

public static String getRelativePath(File parent, File f) 

Method Source Code


//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;
    }
}

Related

  1. getRelativePath(File home, File f)
  2. getRelativePath(File home, File f)
  3. getRelativePath(File original, File directory)
  4. getRelativePath(File parent, File child)
  5. getRelativePath(File parent, File child)
  6. getRelativePath(File parentDirectory, File file)
  7. getRelativePath(File path, File base)
  8. getRelativePath(File path, File basePath)
  9. getRelativePath(File ref_file, File tst_file)