Details
-
New Feature
-
Status: Resolved
-
Minor
-
Resolution: Won't Do
-
None
-
None
-
None
-
n/a
Description
Please consider adding the following method to org.apache.commons.io.FileUtils. I've submitted the method, with test cases below (rather than create a patch file). As a single method, it should prove very simple to integrate.
The method returns the path to a file, from another file, as described in the Javadoc method header below:
/** * Returns the path of a aFile relative to another aFile, for example the location of a file: * <code>resources/language/english/foobar.properties</code> relative to * <code>resources/language/japanese/foobar.properties</code> is * <code>../../english/foobar.properties</code> * * @param aFile the aFile to check relative location * @param fromAnotherFile the base location * @return the relative location path * @throws java.io.IOException on IO error */ public static String pathTo(File aFile, File fromAnotherFile) throws IOException { LOGGER.debug("Find path to file: " + aFile.toString() + " from file: " + fromAnotherFile.toString()); Stack<File> fileToDirectories = directoriesFor(aFile); Stack<File> fileFromDirectories = directoriesFor(fromAnotherFile); while (fileToDirectories.peek().equals(fileFromDirectories.peek())) { fileToDirectories.pop(); fileFromDirectories.pop(); if (fileToDirectories.isEmpty() || fileFromDirectories.isEmpty()) { break; } } StringBuilder pathToCommonParentDirectory = new StringBuilder(); while (!fileFromDirectories.isEmpty()) { pathToCommonParentDirectory.append("../"); fileFromDirectories.pop(); } StringBuilder pathToFileFromCommonParentDirectory = new StringBuilder(); while (!fileToDirectories.isEmpty()) { pathToFileFromCommonParentDirectory.append(fileToDirectories.pop().getName()); if (!fileToDirectories.isEmpty()) { pathToFileFromCommonParentDirectory.append("/"); } } return pathToCommonParentDirectory.toString() + pathToFileFromCommonParentDirectory.toString(); } private static Stack<File> directoriesFor(File file) throws IOException { Stack<File> pathElements = new Stack<File>(); for (File element = file.getCanonicalFile(); element != null; element = element.getParentFile()) { pathElements.push(element); } return pathElements; }
. . . this is useful for batch processing, web applications, etc.
Test Cases:
@Test public void pathTo() throws IOException { //Setup File file1 = new File("configs/js/en/a.xml"); File file2 = new File("configs/js/ja/a.xml"); Assert.assertNotNull(file1); Assert.assertNotNull(file2); //Test Assert.assertEquals("../../en/a.xml", FileUtils.pathTo(file1, file2)); } @Test public void pathTo_windowsStyleOnUnixMachine() throws IOException { File file1 = new File("c:/fred/foobar/dude.properties"); File file2 = new File("c:/data/zz.txt"); Assert.assertEquals("../../fred/foobar/dude.properties", FileUtils.pathTo(file1, file2)); Assert.assertEquals("../../../data/zz.txt", FileUtils.pathTo(file2, file1)); } @Test public void pathTo_fromParentDirectory() throws IOException { File file1 = new File("ui-performance-enhancer/out/test/ui-performance-enhancer/configs/css/imported.xml"); File file2 = new File("ui-performance-enhancer/out/test/ui-performance-enhancer/configs/css"); Assert.assertEquals("imported.xml", FileUtils.pathTo(file1, file2)); }