Reputation: 19877
I have an absolute path to file A.
I have a relative path to file B from file A's directory. This path may and will use ".." to go up the directory structure in arbitrarily complex ways.
Example A:
C:\projects\project1\module7\submodule5\fileA
Example Bs:
..\..\module3\submodule9\subsubmodule32\fileB
..\submodule5\fileB
..\..\module7\..\module4\submodule1\fileB
fileB
How do I combine the two in order to get the simplest possible absolute path to file B?
Upvotes: 49
Views: 69979
Reputation: 301
String absolutePath = FileSystems.getDefault().getPath(mayBeRelativePath).normalize().toAbsolutePath().toString();
Upvotes: 30
Reputation: 1949
From your question, if i could get it right, you are looking to get abolute path from relative path, then you can do following.
File b = new File("../some/relative/path");
String absolute = b.getCanonicalPath(); // may throw IOException
or shorthand notation can be,
String absolute = new File("../some/relative/path").getCanonicalPath();
Upvotes: 5
Reputation: 5417
I know it isn't the best solution but can't you just combine the substring of fileA's path from 0 to the lastIndexOf("\")
with fileB's path.
Example A:
C:\projects\project1\module7\submodule5\fileA
Example Bs:
..\..\module3\submodule9\subsubmodule32\fileB
C:\projects\project1\module7\submodule5\..\..\module3\submodule9\subsubmodule32\fileB
If you don't want the ..
in there then, it would take longer, but I recommend going through the path for fileB
and keep taking the substring from 0 to the first index of \
. Then check the substring. If it is ..
then remove the substring from there and remove the substring from fileA's
path from lastIndexOf(\)
to length. Then repeat. That way you are removing the folders you don't need and the ..s
.
So :
Example A:
C:\projects\project1\module7\submodule5\fileA
Example Bs:
..\..\module3\submodule9\subsubmodule32\fileB
--> C:\projects\project1\module3\submodule9\subsubmodule32\fileB
Upvotes: 0
Reputation: 1
Windows path to full Java path.
String winPath = downloadPath+"\\"+dir_contents[i].getName();
String absPath = winPath.replace("\\","\\\\");
Upvotes: -3
Reputation: 27296
What's better than just creating a utility that converts relative paths to absolute paths is to create a utility that converts any path passed to it into an absolute path so that you don't have to check on the client-side.
The below code works for me in both cases and I've used the String
type at the signature of the method (both parameter and return value):
public static String toAbsolutePath(String maybeRelative) {
Path path = Paths.get(maybeRelative);
Path effectivePath = path;
if (!path.isAbsolute()) {
Path base = Paths.get("");
effectivePath = base.resolve(path).toAbsolutePath();
}
return effectivePath.normalize().toString();
}
Changing the above code to expose Path
types on the signature of the method is trivial (and actually easier) but I think that using String
on the signature gives more flexibility.
Upvotes: 1
Reputation: 391
In Java 7 you can also use the Path interface:
Path basePath = FileSystems.getDefault().getPath("C:\\projects\\project1\\module7\\submodule5\\fileA");
Path resolvedPath = basePath.getParent().resolve("..\\..\\module3\\submodule9\\subsubmodule32\\fileB"); // use getParent() if basePath is a file (not a directory)
Path abolutePath = resolvedPath.normalize();
Upvotes: 16
Reputation: 312
Here is the sample code that works for me.
public String absolutePath(String relative, String absoluteTo)
{
String[] absoluteDirectories = relative.split("\\\\");
String[] relativeDirectories = absoluteTo.split("\\\\");
int relativeLength = relativeDirectories.length;
int absoluteLength = absoluteDirectories.length;
int lastCommonRoot = 0;
int index;
for (index = 0; index < relativeLength; index++)
if (relativeDirectories[index].equals("..\\\\"))
lastCommonRoot = index;
else
break;
StringBuilder absolutePath = new StringBuilder();
for (index = 0; index < absoluteLength - lastCommonRoot; index++)
{
if (absoluteDirectories[index].length() > 0)
absolutePath.append(absoluteDirectories[index] + "\\\\");
}
for (index = lastCommonRoot; index < relativeLength - lastCommonRoot;
index++)
{
if (relativeDirectories[index].length() > 0)
absolutePath.append(relativeDirectories[index] + "\\\\");
}
return absolutePath.toString();
}
Also I the conversion to relative:
public String relativePath(String absolute, String relativeTo) throws Exception
{
String[] absoluteDirectories = absolute.split("\\\\");
String[] relativeDirectories = relativeTo.split("\\\\");
int length = absoluteDirectories.length < relativeDirectories.length ?
absoluteDirectories.length : relativeDirectories.length;
int lastCommonRoot = -1;
int index;
for (index = 0; index < length; index++)
if (absoluteDirectories[index].equals(relativeDirectories[index]))
lastCommonRoot = index;
else
break;
if (lastCommonRoot > -1){
StringBuilder relativePath = new StringBuilder();
for (index = lastCommonRoot + 1; index <absoluteDirectories.length;
index++)
if (absoluteDirectories[index].length() > 0)
relativePath.append("..\\\\");
for (index = lastCommonRoot + 1; index <relativeDirectories.length-1;
index++)
relativePath.append(relativeDirectories[index] + "\\\\");
relativePath.append(relativeDirectories[relativeDirectories.length - 1]);
return relativePath.toString();
}
else{
throw new Exception("No common root found between working direcotry and filename");
}
}
Upvotes: 0
Reputation: 45754
If I get your problem right, you could do something like this:
File a = new File("/some/abs/path");
File parentFolder = new File(a.getParent());
File b = new File(parentFolder, "../some/relative/path");
String absolute = b.getCanonicalPath(); // may throw IOException
Upvotes: 53