Java Path Relative Get getRelativePath(File source, File target)

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

Description

Get a relative path pointing from one File to another.

License

Open Source License

Parameter

Parameter Description
source A File to point from.
target A file to point to.

Return

A path String pointing from source to target.

Declaration

static String getRelativePath(File source, File target)
        throws IOException 

Method Source Code

//package com.java2s;
//License from project: Open Source License 

import java.io.*;
import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;

public class Main {
    /**//from  w  w  w.jav a2  s. c om
     * Get a relative path pointing from one File to another.
     * @param source A File to point from.
     * @param target A file to point to.
     * @return A path String pointing from source to target.
     */
    static String getRelativePath(File source, File target)
            throws IOException {
        source = new File(source.getCanonicalPath());
        target = new File(target.getCanonicalPath());
        File common = getCommonAncestor(source, target);
        if (common == null) {
            return null;
        }
        String upPath = getRelativeAncestor(common, source);
        String downPath = getRelativeDescendant(common, target);
        String path;
        if ((upPath.length() > 0) && (downPath.length() > 0)) {
            path = upPath + File.separatorChar + downPath;
        } else {
            path = upPath + downPath;
        }
        return path;
    }

    /**
     * Find a common ancestor File of the two given Files, if one exists.
     * If no such common ancestor exists, return null.
     */
    static File getCommonAncestor(File f1, File f2) {
        List a1 = getAncestors(f1);
        List a2 = getAncestors(f2);
        Iterator i1 = a1.iterator();
        Iterator i2 = a2.iterator();
        Object common = null;
        while (i1.hasNext() && i2.hasNext()) {
            Object o1 = i1.next();
            Object o2 = i2.next();
            if (!o1.equals(o2)) {
                break;
            }
            common = o1;
        }
        return (File) common;
    }

    /**
     * Get a relative path pointing from a descendant to an ancestor.
     * @return A relative File, pointing from the descendant to the ancestor.
     * @throws IllegalArgumentException If the given descendant is not
     * actually a descendant of the given ancestor.
     */
    private static String getRelativeAncestor(File ancestor, File descendant) {
        List ancestors = getAncestors(descendant);
        if (!ancestors.contains(ancestor)) {
            throw new IllegalArgumentException("The file \""
                    + descendant.getPath() + "\" "
                    + "does not have ancestor \"" + ancestor.getPath()
                    + "\".");
        }
        // Move an iterator to the location of the ancestor:
        Iterator i = ancestors.iterator();
        File f;
        do {
            f = (File) i.next();
        } while (!ancestor.equals(f));

        // Construct a path String from the remaining iterations:
        StringBuffer path = new StringBuffer();
        while (i.hasNext()) {
            i.next();
            path.append("..");
            if (i.hasNext()) {
                path.append(File.separatorChar);
            }
        }
        return path.toString();
    }

    /**
     * Get a relative path pointing from an ancestor to a descendant.
     * @return A relative File, pointing from the ancestor to the descendant.
     * @throws IllegalArgumentException If the given descendant is not
     * actually a descendant of the given ancestor.
     */
    private static String getRelativeDescendant(File ancestor,
            File descendant) {
        List ancestors = getAncestors(descendant);
        if (!ancestors.contains(ancestor)) {
            throw new IllegalArgumentException("The descendant \""
                    + descendant.getPath() + "\" "
                    + "does not have ancestor \"" + ancestor.getPath()
                    + "\".");
        }
        // Move an iterator to the location of the ancestor:
        Iterator i = ancestors.iterator();
        File f;
        do {
            f = (File) i.next();
        } while (!ancestor.equals(f));

        // Construct a path String from the remaining iterations:
        StringBuffer path = new StringBuffer();
        while (i.hasNext()) {
            f = (File) i.next();
            path.append(f.getName());
            path.append(File.separatorChar);
        }
        path.append(descendant.getName());

        return path.toString();
    }

    /**
     * Get a List of ancestor Files of a given File, in order from highest to
     * lowest ancestor and not including the File itself.
     */
    static List<File> getAncestors(File file) {
        LinkedList<File> list = new LinkedList<File>();
        file = file.getParentFile();
        if (file == null) {
            return list;
        }
        do {
            list.addFirst(file);
            file = file.getParentFile();
        } while (file != null);
        return list;
    }
}

Related

  1. getRelativePath(File root, File file)
  2. getRelativePath(File root, File file)
  3. getRelativePath(File root, File target, String fileSeparator)
  4. getRelativePath(File rootDirectory, File file)
  5. getRelativePath(File source, File destination)
  6. getRelativePath(File src, File dst)
  7. getRelativePath(File subj, File relativeTo)
  8. getRelativePath(File target, File base)
  9. getRelativePath(File target, File relativeTo)