0

I have a problem with System.getProperty("user.dir") giving different directory when run by IDE and when I manually compile & run it in cmd. My thing is this, I have project structure like this:

project
- exports
- src
  - main
    - java
      - Main
- file1
- file2 

One of the args in main method is the name of one of those 2 files, that I then access.

When I configure my run in IDE it works like a charm - the directory I get is C:\Users\**\**\**\project and it is able to read and write to the file.

But when I compile it in cmd javac Main.java and then run it, I get C:\Users\**\**\**\project\src\main\java and because of that, I am unable to access the file without having to modify the path.

My question is, is there like a golden way, that would work for both these cases, without me having to alter the returned path?

EDIT:

For clear understanding, I know what System.getProperty("user.dir") returns, but my question was, if it is possible to get the same result somehow with using Path or if I have to get the path and edit it, so that it will end in project directory?

in IDE I get: C:\Users\petri\Desktop\CZM\bicycle-statistics

in cmd: C:\Users\petri\Desktop\CZM\bicycle-statistics\src\main\java

I want to get the same path in cmd, that I got in IDE.

I tried using Paths.get("").toAbsolutePath(), but it is the same thing.

So, what I did is this:

Path path = Paths.get("").toAbsolutePath();
while (!path.endsWith("project")) {
    path = path.getParent();
}

And it works, but I am trying to ask, if there is some more elegant way, because I will have to defend my solution in front of my supervisor.

AP11
  • 617
  • 4
  • 11
  • Does this answer your question? [Java - using System.getProperty("user.dir") to get the home directory](https://stackoverflow.com/questions/24709769/java-using-system-getpropertyuser-dir-to-get-the-home-directory) – PythonLearner Feb 23 '21 at 18:25
  • `C:\Users\..\..\..\project` are the `..` segments literally two dots, or just stand for some other directory name? If they are literal, that resolves to `C:\project`. – Jim Garrison Feb 23 '21 at 18:25
  • @JimGarrison they are normal folder names,like e.g. `Documents` – AP11 Feb 23 '21 at 18:27
  • Please don't use `..` to represent literal directory names. `..` means something specific in a path, and using that particular set of characters gives the wrong idea. I'd suggest that you use `C:\Users\**\**\foo\bar` or something like that instead. Anything but `..`. – CryptoFool Feb 23 '21 at 18:29
  • My recommendation is that you never rely on the result of `System.getProperty("user.dir")`, or any other path that requires particular behavior outside of your code. IMO, there are only two good ways to find a particular file: 1) in relation to a known location, like in the classpath, or in the current user's home directory, or 2) via a passed in **absolute** path. Just my $.02, but I've been doing this a long time, and trying to use the current working directory or the value of a system property or environment variable you didn't set explicitly is just asking for trouble. – CryptoFool Feb 23 '21 at 18:32
  • ...in case it isn't clear, I fully support the use of `System.getProperty("user.home")`, as that is a known location that does not change based on how and where a program is executed. – CryptoFool Feb 23 '21 at 18:36
  • Alright, thank you all for your time, I really appreciate it! – AP11 Feb 23 '21 at 18:52
  • The project directory is not important. Consider that, at runtime, you do not know how your project is being executed. It could be from a directory in a filesystem, from a .jar file, or even from a jar transmitted over a network. There might not even be a filesystem under you. The ONLY thing you can refer to is the base resource path defined by your class loader. – Jim Garrison Feb 23 '21 at 18:56
  • @JimGarrison ok, that's just outside of my knowledge reach, I think I have to look into JVM more to understand this, but still, thank you for your time, sir. – AP11 Feb 23 '21 at 19:05
  • You can refer to things in the filesystem, _if there is a filesystem_, but things like `user.dir` and `user.home` may be totally unrelated to what you can actually access. You can reliably access something relative to the class loader, or , as @CryptoFool says, only an absolute path, passed in via some mechanism (provided as input or on the command line). What you can't ever assume, if you want your code to be bullet-proof, is that there is a "current directory". – Jim Garrison Feb 23 '21 at 19:50

2 Answers2

1

Normally your IDE will build source files in src/main/java and write the class files out to some other directory, like target/classes.

If your IDE built the project that way, then you can run it from the command line by switching to your project directory (cd C:\Users\**\**\**\project using your example) and then running:

java -classpath target/classes Main

assuming that target/classes is where your IDE put the files. If you really do have the class files in the source directory, then use -classpath src/main/java.

If you always run the program from the project directory, then you can assume within the program that the current directory is the project directory. You don't even have to use user.dir then, just use relative path names for everything, e.g., path/to/whatever.dat will automatically resolve to C:\Users\**\**\**\project\path\to\whatever.dat.

Willis Blackburn
  • 8,068
  • 19
  • 36
  • Thank you, but in my IDE it works just fine, my problem is when I run it in cmd it return the directory that my `Main` class is located in, rather than returning the project directory. – AP11 Feb 23 '21 at 18:49
  • Right. My point is, don't run it from the directory containing `Main`, run it from the project directory, and use `-classpath` to tell Java where the classes are. – Willis Blackburn Feb 23 '21 at 19:13
1

One of the args in main method is the name of one of those 2 files

Then make sure you enter the name correctly.

E.g. if the current working directory is the project folder, then name file1 will refer to the file1 file. If the current working directory is the java folder, then the argument to the program needs to be ..\..\..\file1.

That is because you give relative file names, which means they are relative to the current working directory.

Alternatively, give a fully qualified name, then the argument will be the same, regardless of what the current working directory is:

C:\Users\**\**\**\project\file1

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Yes, I actually did that, but the problem is when I share my work with my "supervisor" and he tries to run it in his workplace. That's why I am asking if it is possible to obtain the absolute path in a particular way, or if I have to alter the path. – AP11 Feb 23 '21 at 18:42
  • 1
    Drop a script into your project directory that runs your program with the classpath (described in my answer) and tell your supervisor to run that. – Willis Blackburn Feb 23 '21 at 18:45
  • @AP11 When you supervisor runs the code, (s)he should know how working directories work, and correctly qualify the file name, depending on how the code is executed. If supervisor doesn't even know how working directories function, then you shouldn't be giving the supervisor source code, but a runnable jar, and the with the jar and file right next to each other, running the program will be a breeze. – Andreas Feb 23 '21 at 18:47
  • Well, that's true and my first solution was actually manually changing the path to project to ease my pain, as the variable with project path solved the `IDE & cmd` problem I had, but he insisted on me doing it automatically. – AP11 Feb 23 '21 at 18:51
  • @AP11 Automatically = script, as Willis commented, so create a `.bat` file to do the compile and run. You should also consider using a build script. – Andreas Feb 23 '21 at 18:57
  • Alright, I'll look into this. Thank you both guys Andreas and @WillisBlackburn I really appreciate it. – AP11 Feb 23 '21 at 19:02
  • If you're using Maven to build your project, it can generate that launcher script for you automatically using the Application Assembler plug-in. That's what Java projects do; nobody expects users of a Java program to run it directly from the command line. – Willis Blackburn Feb 23 '21 at 19:12