Joining paths in Java

Java

Java Problem Overview


In Python I can join two paths with os.path.join:

os.path.join("foo", "bar") # => "foo/bar"

I'm trying to achive the same in Java, without worrying if the OS is Unix, Solaris or Windows:

public static void main(String[] args) {
	Path currentRelativePath = Paths.get("");
	String current_dir = currentRelativePath.toAbsolutePath().toString();
	String filename = "data/foo.txt";
	Path filepath = currentRelativePath.resolve(filename);
	
    // "data/foo.txt"
	System.out.println(filepath);
    
}

I was expecting that Path.resolve( ) would join my current directory /home/user/test with data/foo.txt making /home/user/test/data/foo.txt. What am I getting wrong?

Java Solutions


Solution 1 - Java

Even though the original solution for getting the current directory using the empty String works. But is recommended to use the user.dir property for current directory and user.home for home directory.

Path currentPath = Paths.get(System.getProperty("user.dir"));
Path filePath = Paths.get(currentPath.toString(), "data", "foo.txt");
System.out.println(filePath.toString());

output:

/Users/user/coding/data/foo.txt

From Java Path class Documentation: >A Path is considered to be an empty path if it consists solely of one name element that is empty. Accessing a file using an empty path is equivalent to accessing the default directory of the file system.


Why Paths.get("").toAbsolutePath() works

When an empty string is passed to the Paths.get(""), the returned Path object contains empty path. But when we call Path.toAbsolutePath(), it checks whether path length is greater than zero, otherwise it uses user.dir system property and return the current path.

Here is the code for Unix file system implementation: UnixPath.toAbsolutePath()


Basically you need to create the Path instance again once you resolve the current directory path.

Also I would suggest using File.separatorChar for platform independent code.

Path currentRelativePath = Paths.get("");
Path currentDir = currentRelativePath.toAbsolutePath(); // <-- Get the Path and use resolve on it.
String filename = "data" + File.separatorChar + "foo.txt";
Path filepath = currentDir.resolve(filename);

// "data/foo.txt"
System.out.println(filepath);

Output:

/Users/user/coding/data/foo.txt

Solution 2 - Java

Paths#get(String first, String... more) states,

> Converts a path string, or a sequence of strings that when joined form a path string, to a Path.

> ...

> A Path representing an empty path is returned if first is the empty > string and more does not contain any non-empty strings.

To get the current user directory you can simply use System.getProperty("user.dir").

Path path = Paths.get(System.getProperty("user.dir"), "abc.txt");
System.out.println(path);

Moreover, get method uses variable length argument of String, which will be used to provide subsequent path strings. So, to create Path for /test/inside/abc.txt you have to use it in a following way,

Path path = Paths.get("/test", "inside", "abc.txt");

Solution 3 - Java

Not an specific method.

If you use java 8 or better, you have 2 options:

a) Use java.util.StringJoiner

StringJoiner joiner = new StringJoiner(File.pathSeparator); //Separator
joiner.add("path1").add("path2");
String joinedString = joiner.toString();

b) Use String.join(File.pathSeparator, "path1", "path2");

If you use java 7 or lower, you may use commons-lang library from apache commons. The class StringUtils has a method to join strings using a separator.

c) StringUtils.join(new Object[] {"path1", "path2"}, File.pathSeparator);

A sidenote: You may use linux pathseparator "/" for windows (Just remember that absolute paths are something like "/C:/mydir1/mydir2". Using always "/" is very useful if you use protocols such as file://

Solution 4 - Java

You can do like

// /root
Path rootPath = Paths.get("/root");
// /root/temp
Path temPath = rootPath.resolve("temp");

A good detailed post is here Path Sample Usecase

Solution 5 - Java

The most basic way is:

Path filepath = Paths.get("foo", "bar");

You should never write Paths.get(""). I'm surprised that works at all. If you want to refer to the current directory explicitly, use Paths.get(System.getProperty("user.dir")). If you want the user's home directory, use Paths.get(System.getProperty("user.home")).

You can also combine the approaches:

Path filepath = Paths.get(
    System.getProperty("user.home"), "data", "foo.txt");

Solution 6 - Java

The most reliable, platform-independent way to join paths in Java is by using Path::resolve (as noted in the JavaDoc for Paths::get). For an arbitrary-length array of Strings representing pieces of a path, these could be joined together using a Java Stream:

private static final String[] pieces = {
	System.getProperty("user.dir"),
	"data",
	"foo.txt"};
public static void main (String[] args) {
	Path dest = Arrays.stream(pieces).reduce(
	/* identity    */ Paths.get(""),
	/* accumulator */ Path::resolve,
	/* combiner    */ Path::resolve);
	System.out.println(dest);
}

Solution 7 - Java

For Java >= 11 the recommended way now is to use Path.of instead of Paths.get, as suggested by previous answers. Quoting from Java 11 docs:

> It is recommended to obtain a Path via the Path.of methods instead of via the get methods defined in this class as this class may be deprecated in a future release.

E.g., the following will join "foo" and "bar", according to the OS path separator:

import java.nio.file.Path;
...

Path fooBar = Path.of("foo", "bar");

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncybertextronView Question on Stackoverflow
Solution 1 - JavaYoungHobbitView Answer on Stackoverflow
Solution 2 - JavaakashView Answer on Stackoverflow
Solution 3 - JavaRober2D2View Answer on Stackoverflow
Solution 4 - JavaRobin MathurView Answer on Stackoverflow
Solution 5 - JavaVGRView Answer on Stackoverflow
Solution 6 - JavaPatrick ParkerView Answer on Stackoverflow
Solution 7 - JavaasherbretView Answer on Stackoverflow