Mega Code Archive

 
Categories / Java / File Input Output
 

Collection of file path related stuff

import java.io.File; import java.io.IOException; import java.util.ArrayList; /**  * Collection of file path related stuff  * @author eliott bartley  */ public class PathTools {     private static class PathList extends ArrayList<String> { }     private PathTools() { }     /**      * Turn a relative path or filename into an absolute one      * @param relativePath The relative path to convert to an absolute one      * @return The absolute path of the <var>relativePath</var>      */     public static String getAbsolutePath(String relativePath)     {   return getAbsolutePath(relativePath, null, true);     }     /**      * Turn a relative path or filename into an absolute one, relative to a      *  directory other than the current directory      * @param relativePath The relative path to convert to an absolute one      * @param workingPath The home path from which the relative path is from. If      *  this is null, the current working path is used      * @return The absolute path of the <var>relativePath</var>      */     public static String getAbsolutePath(String relativePath, String workingPath)     {   return getAbsolutePath(relativePath, workingPath, true);     }     /**      * Turn a relative path or filename into an absolute one      * @param relativePath The relative path to convert to an absolute one      * @param addSlash Specify true if returned path must end with a '/', false      *  if it's not important      * @return The absolute path of the <var>relativePath</var>      */     public static String getAbsolutePath(String relativePath, boolean addSlash)     {   return getAbsolutePath(relativePath, null, addSlash);     }     /**      * Turn a relative path or filename into an absolute one, relative to a      *  directory other than the current directory      * @param relativePath The relative path to convert to an absolute one      * @param addSlash Specify true if returned path must end with a '/', false      *  if it's not important      * @return The absolute path of the <var>relativePath</var>      */     public static String getAbsolutePath     (   String relativePath,         String workingPath,         boolean addSlash     ){  File file;         String path;         if(relativePath == null)             return null;         file = new File(relativePath);         if(file.isAbsolute() == false)         {   file = new File(workingPath, relativePath);             try { path = file.getCanonicalPath(); }             catch(IOException e) { path = file.getAbsolutePath(); }         }         else             path = relativePath;         // Make sure the path end with a '/' if one is required         //  (addSlash == true)         if(addSlash == true && file.isDirectory() == true)             path = getSafePath(path);         return path.replace("\\", "/");     }     /**      * Break a path down into individual elements and add to a list.      *  example : if a path is /a/b/c/d.txt, the breakdown will be [d.txt,c,b,a]      * @param relativeFile input file      * @return a List collection with the individual elements of the path in      *  reverse order      */   private static PathList getPathList     (   String relativePath,         String workingPath     ){  PathList pathList = new PathList();         File relativeFile = new File(relativePath);         File pathParser;         try         {             if(workingPath == null || relativeFile.isAbsolute() == true)                 pathParser = relativeFile.getCanonicalFile();             else                 pathParser = new File                 (   workingPath,                     relativePath                 ).getCanonicalFile();             for             (   ;                 pathParser != null;                 pathParser = pathParser.getParentFile()             )   if(pathParser.getName().length() != 0)                     pathList.add(pathParser.getName());                 else                     pathList.add(pathParser.getPath());         }         catch(IOException e)         {   // This is for debugging only - the user is notified of the error             //  when the calling code gets a pathList of null back and tries             //  to use it as a valid path, and fails, and then tells the user             //  'path does not exist!' or so -- so this exception shouldn't show             //  an error message, other than the debugging one it's showing             //  currently (2008y07M31d), which could be removed in the future,             //  or, if you don't see it (just under this comment), was removed             //  in the past.             System.err.format             (   "relativePath [%s] workingPath [%s]%n",                 relativePath,                 workingPath             );             e.printStackTrace();             pathList = null;         }         return pathList;     }     /**      * Figure out a string representing the relative path of      * 'absolutePath' with respect to 'workingPath'      * @param workingPath home path      * @param absolutePath path of file      */     private static String parsePathLists     (   PathList workingPath,         PathList absolutePath     ){  int i;         int j;         StringBuilder relativePath = new StringBuilder();         // start at the beginning of the lists         // iterate while both lists are equal         i = workingPath.size() - 1;         j = absolutePath.size() - 1;          // first eliminate common root          while         (   i >= 0 && j >= 0          && workingPath.get(i).equals(absolutePath.get(j))         ){  i--;             j--;         }         // for each remaining level in the home path, add a ..         for(; i>=0; i--)             relativePath.append(".." + File.separator);         // for each level in the file path, add the path         for(; j>=0; j--)             if(j > 0)                 relativePath.append(absolutePath.get(j) + File.separator);             else                 relativePath.append(absolutePath.get(j));         return relativePath.toString();     }     /**      * Get relative path of absolutePath from the current directory. The      *  resulting path will end with a path separator      * @param absolutePath file to generate path for      * @return path from workingPath to absolutePath as a string      */     public static String getRelativePath     (   String absolutePath     ){  return getRelativePath(absolutePath, null, true);     }     /**      * Get relative path of absolutePath from the current directory, optionally      *  appending the result with a path separator      * @param absolutePath file to generate path for      * @param addSlash true to terminate the result with a path separator      * @return path from workingPath to absolutePath as a string      */     public static String getRelativePath     (   String absolutePath,         boolean addSlash     ){  return getRelativePath(absolutePath, null, addSlash);     }     /**      * Get relative path of absolutePath from the current directory. The      *  resulting path will end with a path separator      * @param absolutePath file to generate path for      * @param workingPath base path, should be a directory, not a file, or it      *  doesn't make sense      * @return path from workingPath to absolutePath as a string      */     public static String getRelativePath     (   String absolutePath,         String workingPath     ){  return getRelativePath(absolutePath, workingPath, true);     }     /**      * Get relative path of absolutePath from workingPath, optionally      *  appending the result with a path separator      * @param absolutePath file to generate path for      * @param workingPath base path, should be a directory, not a file, or it      *  doesn't make sense      * @param addSlash true to terminate the result with a path separator      * @return path from workingPath to absolutePath as a string      */     public static String getRelativePath     (   String absolutePath,         String workingPath,         boolean addSlash     ){  String path;         if(workingPath == null)             workingPath = getAbsolutePath(".");         absolutePath = absolutePath.trim();         workingPath = workingPath.trim();         path = parsePathLists         (   getPathList(workingPath, null),             getPathList(absolutePath, workingPath)         );         // Make sure the paths end with a '/' if one is required         if(addSlash == true         && new File(getAbsolutePath(path, workingPath)).isDirectory() == true)             path = getSafePath(path);         return path.replace("\\", "/");     }     /**      * Ensure a path ends with a '/'      * @param path The path to fix      * @return The <var>path</var>, with a trailing '/'      */     public static String getSafePath(String path)     {   if(path == null || path.length() == 0)             return "./";         if(path.charAt(path.length() - 1) != '/'         && path.charAt(path.length() - 1) != '\\')             path += "/";         return path;     }     /**      * Build a file list of all the files in the specified directories matching      *  the specified wildcard. pathList can contain several paths separated by      *  a semi-colon (;) e.g. "c:/.*\\.txt;c:/.*\\.dat" search for *.txt or      *  *.dat in c:/. Wildcards use regular expression syntax e.g.      *  "c:/[0-9]{5}\\.txt" search for files made up of 5 numeric digits      *  followed by .txt. Wildcards can also appear in folder names, e.g.      *  "c:/my .* /.*" search for all files under c that are in a folder      *  starting my.. i.e. my document, my videos, etc. Folder searches can be      *  recursive too, by starting the folder name with N: where N is the      *  maximum depth of the search, or * for no limit, e.g. "c:/*:my .* /.*"      *  search for all files under all folders in c: (search the whole drive)      *  that start my.., or "c:/3:.* /.*\\.txt" search for .txt files in all      *  folders up to a maximum of 3 levels deep, i.e. is the same as      *  "c:/.* /.* /.* /.*\\.txt". Note: because \\ is regular expression syntax,      *  it cannot be used as a path separator, use only / as a path separator      * @param pathList The list of semi-colon (;) separated paths to search      * @return Array of all files matching the path, includes pathname      */     public static String[] fileList(String pathList)     {   PathList files = new PathList();         String[] paths = pathList.split(";");         for(String path : paths)             fileList("", null, path.split("/"), 0, files, null, 0);         return files.toArray(new String[files.size()]);     }     /**      * Recursively get a list of files matching a given wildcard      * @param base The parent folder that was recursed      * @param folder The folder this recursion is now looking into      * @param folders Array of all folders making up the path      * @param index Index into the folders array that is of importance now      * @param files List of files currently found that matched      * @param wildcard If a folder repeats a wildcard *:.*, the wildcard to      *  repeat      * @param repeat If a folder repeats a wildcard, how many more times it      *  needs to repeat      */     private static void fileList     (   String      base,         String    folder,         String[] folders,         int        index,         PathList   files,         String  wildcard,         int       repeat     ){  File        file; // file referring to the current folder         String[] results; // list of files found in current folder         int        colon; // locate colon in repeat wildcard 3:.*         int  localRepeat; // repeating wildcard at this level, hides wildcard                           //  inherited during recursion (wilecard, repeat) with                           //  (folders[index], localRepeat)         // If the folder to check now is unknown, use the folder specified in         //  the folder-array. The folder can differ from the folder-array if the         //  folder-array had .*, folder will be the actual folder that matched         //  that wildcard; folder is initially null, so fix it to the root         //  folder to search         if(folder == null)             folder = folders[index];         // Fix up the base so that it now refers to base + current folder         //  base is initially ""         base += folder + "/";         // Move on to the next folder, it is what we're looking for now in this         //  path         index++;         // Drop one level in the repeat wildcard search, while this is > 0, this         //  folder will be searched for the actual folder[index], but also what         //  the repeat wildcard is, so c:/*:.*/.*\\.txt will match a .txt in         //  c:/a/x.txt, but this repeat will also repeat *:.* under a, so will         //  also match c:/a/b/y.txt, etc.. Also, MAX_VALUE means infinity, so         //  don't decrement in that case         if(repeat > 0 && repeat < Integer.MAX_VALUE)             repeat--;         // Get a list of files under the current path         file = new File(base);         results = file.list();         // Parse out the repeat information, if any         colon = folders[index].indexOf(':');         localRepeat = 0;         if(colon != -1)             try             {                 // Repeat can be N: (where N is a number) or *: - this will not                 //  match c:/ as c isn't a number or an '*'                 String parseRepeat = folders[index].substring(0, colon);                 if(parseRepeat.equals("*") == true)                     localRepeat = Integer.MAX_VALUE;                 else                     localRepeat = Integer.parseInt(parseRepeat);                 // Update the folder so it no longer includes the X: part                 folders[index] = folders[index].substring(colon + 1);             }             catch(NumberFormatException e) { }         // First check against the current wildcard         if(results != null)             // If still looking in folders..             if(index < folders.length - 1)                 for(String result : results)                 {   if(result.matches(folders[index]) == true)                         // Recursively search sub-folders if this folder matched                         //  the wildcard                         fileList                         (   base,                             result,                             folders,                             index,                             files,                             // if no repeat is set up, localRepeat will be 0 so                             //  passing this repeat information will not                             //  actually repeat if it's not set up to do so                             folders[index],                             localRepeat                         );                 }             else             // If reached the last part of the search string, then these are the             //  files being searched for, so store the matches                 for(String result : results)                     if(result.matches(folders[index]) == true)                         files.add(base + result);         // Next test all the results against the repeat wildcard, if any         if(results != null         && repeat > 0)             for(String result : results)                 if(result.matches(wildcard) == true)                     // Recursively search sub-folders if this folder matched the                     //  repeat wildcard                     fileList                     (   base,                         result,                         folders,                         // As this is a repeat, bring the index back so the sub-                         //  dir search uses the same folder as currently used -                         //  this -1 will propagate all the way up the recursion                         //  causing all sub-levels, no matter how deep, to reuse                         //  the same index                         index - 1,                         files,                         wildcard,                         repeat                     );     } }