1

This is a follow-up question to this one (just as a brief description: I have been able to run a Java program by double-clicking on the .jar file on OS X and Windows, but not on Linux, as with the latter I get a file path problem).

Through trying out a few things using NetBeans under Ubuntu (12.04) I found that the problem seems to be located in what the program considers to be its working directory (which I concluded from the output of File.getAbsolutePath()). If I start my application in NetBeans, everything works (even under Ubuntu), and

System.out.println(new File(".").getAbsolutePath());

gives me /home/my_home/projects/VocabTrainer/., which is my project folder and thus correct. However, if I double-click on the .jar file, located in /home/my_home/projects/VocabTrainer/dist, the output I get under Ubuntu suddenly is merely /home/my_home/. This is problematic as I want to access a data file which is located in a sub-directory of my dist dir.

Does anyone know the cause of this behaviour, and how I can solve the problem?

PS: I don't know if this is required, but here's the output of java -version

java version "1.6.0_24"
OpenJDK Runtime Environment (IcedTea6 1.11.5) (6b24-1.11.5-0ubuntu1~12.04.1)
OpenJDK Server VM (build 20.0-b12, mixed mode)
Community
  • 1
  • 1
canavanin
  • 2,559
  • 3
  • 25
  • 36

2 Answers2

2

I think you're confusing the location of the JAR with the current working directory.

To determine the former, see How to get the path of a running JAR file?

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
1

The cause, not really, at the moment. But you may not want to handle it that way, due to the evident unpredictability. Something like this should get the file, assuming you use the qualified class name of something in the jar in the below getResource call.:

URL url = this.getClass().getClassLoader().getResource("thepackage/ofyourclass/JunkTest.class");  //get url of class file.  expected: ("jar:file:/somepath/dist/yourjar.jar!qualified/class/name.class")
File distDir = null;
if(url.getProtocol() == "jar") {
    String classPath = null;
    String jarPath = url.getPath();
    if(jarPath.matches(".*:.*")) jarPath = new URL(jarPath).getPath();
    classPath = jarPath.split("!")[0];
    distDir = new File(classPath).getParentFile(); //may need to replace / with \ on windows?
} else { //"file" or none
    distDir = new File(url.toURI()).getParentFile();
}    
//... do what you need to do with distDir to tack on your subdirectory and file name

EDIT: I should point out this is clearly hacky. You may be able to add the file's location to the classpath directly at startup (or include the file you're looking for in the jar). From this you could use this.getClass().getClassLoader().getResource() with the filename of what you're looking for directly, which would get you to something like:

URL url = this.getClass().getResource("yourfile");
File file = new File(url.toURI());
//... use file directly from here

FURTHER EDIT: ok, adapted to your missing protocol, and spread it out, so error messages will be more readable for you.

Brian Henry
  • 3,161
  • 1
  • 16
  • 17
  • Thanks for the reply! I have probably done something daft (I'm new to Java...), but URL "url = this.getClass().getClassLoader().getResource("qualified/class/VocabItem.class");" gave me url == null . I simply picked the name of one of my classes, but perhaps I have misunderstood your suggestion!? – canavanin Nov 21 '12 at 22:57
  • ah - replace the "qualified/class" bit with the package of the class in question, assuming you have one. The "qualified class name" of a class is the class name prepended by the package. For this purpose, you need to swap the "." chars for "/" ones. So, if your VocabItem class is in the com.canavanin package, you'd use "com/canavanin/VocabItem.class" for that string. If there's no package, you should be able to omit that part of the string. – Brian Henry Nov 21 '12 at 23:16
  • Thanks for the update. Now I get a MalformedURLExeption though: java.net.MalformedURLException: no protocol: /home/my_home/projects/VocabTrainer/build/classes/my/vocabtrainer/VocabItem.class – canavanin Nov 21 '12 at 23:27
  • Thanks a lot for the edit, I will try it out tonight (it's a private project, so I only work on it at home). – canavanin Nov 22 '12 at 08:21
  • Thank you very much for your help, you've solved my problem! Now everything's back on track :) – canavanin Nov 22 '12 at 21:08