This is a very confuse topic, and we need to understand some concepts before providing a real solution.
The File, and NIO File Api approaches with relative paths ""
or "."
uses internally the system parameter "user.dir"
value to determine the return location.
The "user.dir
" value is based on the USER working directory, and the behavior of that value depends on the operative system, and the way the jar is executed.
For example, executing a JAR from Linux using a File Explorer (opening it by double click) will set user.dir
with the user home directory, regardless of the location of the jar. If the same jar is executed from command line, it will return the jar location, because each cd
command to the jar location modified the working directory.
Having said that, the solutions using Java NIO
, Files
or "user.dir"
property will work for all the scenarios in the way the "user.dir"
has the correct value.
String userDirectory = System.getProperty("user.dir");
String userDirectory2 = new File("").getAbsolutePath();
String userDirectory3 = Paths.get("").toAbsolutePath().toString();
We could use the following code:
new File(MyApp.class.getProtectionDomain()
.getCodeSource()
.getLocation()
.toURI().getPath())
.getParent();
to get the current location of the executed JAR, and personally I used the following approach to get the expected location and overriding the "user.dir"
system property at the very beginning of the application. So, later when the other approaches are used, I will get the expected values always.
More details here -> https://blog.adamgamboa.dev/getting-current-directory-path-in-java/
public class MyApp {
static {
//This static block runs at the very begin of the APP, even before the main method.
try{
File file = new File(MyApp.class.getProtectionDomain().getCodeSource()
.getLocation().toURI().getPath());
String basePath = file.getParent();
//Overrides the existing value of "user.dir"
System.getProperties().put("user.dir", basePath);
}catch(URISyntaxException ex){
//log the error
}
}
public static void main(String args []){
//Your app logic
//All these approaches should return the expected value
//regardless of the way the jar is executed.
String userDirectory = System.getProperty("user.dir");
String userDirectory2 = new File("").getAbsolutePath();
String userDirectory3 = Paths.get("").toAbsolutePath().toString();
}
}
I hope this explanation and details are helpful to others...