1

I am confused about how java load's it's files.

public static File loadFile(String file) throws IOException {
    URL url = ClassLoader.getSystemClassLoader().getResource(file);
    if(url == null){
        throw new IOException("Cannot find: " + file);
    }
    File ret;
    try {
        ret = new File(url.toURI());
        return ret;
    } catch (URISyntaxException e) {
        System.err.println("URISyntaxException in Utility.loadFile(): Tried to load: "+ file);
        throw new IOException("Cannot load: " + file);
    }
}

Here is an (edited) image of the project stucture in Eclipse, where loading the resource works just fine ...

project structure in eclipse

When loading the resouce, I call the above method like this:

char sep = File.seperatorChar;
File file = Utility.loadFile(sep + "res" + sep + "shader"
                                 + sep + "some_shader.glsl");

Though - here is what the .jar looks like (also edited)

contents of the .jar

As soon as I run the jar with java -jar prog.jar , I get:

java.io.IOException: Cannot find: \res\shader\some_shader.glsl

I do not want to use any "relative" path to any kind of class, I always want to use the "absolute" path to the resource from the root of my project's structure (from .../src/... or from ... .jar!/...)

dimo414
  • 47,227
  • 18
  • 148
  • 244
salbeira
  • 2,375
  • 5
  • 26
  • 40

2 Answers2

1

If you load a resource in Java you alway can use '/' as separator.

Try

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL url = classLoader.getResource("res/shader/some_shader.glsl"); // no leading slash

Make shure your JAR with the resource is in your JVM Classpath (-cp or -classpath).

Edit: You must use url.openStream() to get an InputStream - not new File(). Your resource is not a file, becaus it is inside the JAR

drkunibar
  • 1,327
  • 1
  • 7
  • 7
  • Can you tell a little bit more of your enviroment. Is your whole java program in a single jar file? If you open the jar file, can you find `some_shader.glsl` under `res/shader`? – drkunibar Mar 29 '14 at 20:33
  • It actually WAS the usage of the systems specific file seperator AND the usage of a preceeding / in getting the URL – salbeira Mar 29 '14 at 20:35
  • Nice that it works. Are you shure that you use a leading slash (/). I have tried it before a minute on Windows and Ubuntu. I have used the same jar file on both systems - no leading slash and the slash as separator (also on Windows) – drkunibar Mar 29 '14 at 21:46
  • Yes, the PROBLEM was the leading (/) and using (\) in my case of using File.seperatorChar – salbeira Mar 29 '14 at 22:05
0

"Yet again, I am confused about how java load's it's files."

When loading an , you always want to load from the class path, not by File. File will look for resources in the file system, which may work on your file system, but once deployed on a jar, will not work on other systems, and most likely not even yours.

For URLs, what you need to know is where the different ways to obtain a URL will search from. When using a class loader (getClass().getClassLoader().getResource())the search will begin from the root, so this path

"res/shader/some_shader.glsl"

will work. On the other hand, when just using getClass().getResource() without the class loader, the search will begin from the calling class and its package location. That's the the extra / to traverse back in the file structure.

"/res/shader/some_shader.glsl"

UPDATE

I have no idea what you're doing wrong, but I have no problems. You can see the code. I exported it to jar. It works both in Eclipse and in the jar

package stackoverflow;

import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

public class TestImagWithEclipse {
    private static final String PATH = "/res/shader/stack_reverse.png";

    public static void main(String[] args) {
        URL url = TestImagWithEclipse.class.getResource(PATH);
        ImageIcon icon = new ImageIcon(url);
        JOptionPane.showMessageDialog(null, new JLabel(icon), "It works", JOptionPane.PLAIN_MESSAGE);
    }
}

enter image description here

enter image description here

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • When using the getClass.getResource() with the preceeding / , I even get a "not found" in Eclipse ... – salbeira Mar 29 '14 at 19:23
  • @salbeira Run the examples from [this post](http://stackoverflow.com/a/22712062/2587435), using your own paths, and let me know what happens. – Paul Samsotha Mar 29 '14 at 19:27
  • Using the 'Utility.class.getClassLoader().getResource(file)' with preceeding / I get the resource in eclipse, but not in the jar, if I use Utility.class.getResource(file) with the preceeding / I do not find the resource in eclipse. What I did already test was using no / in Utility.class.getClassLoader().getResource(file) , where it works within Eclipse but not the .jar , what I did not test was using no / in Utility.class.getResource(file) in and outside of Eclipse – salbeira Mar 29 '14 at 19:32
  • @salbeira see my UPDATE. Not sure what you're doing wrong but I have no problems. – Paul Samsotha Mar 29 '14 at 19:59
  • I would love to know that, too ... Though ... right now I use 3 different projects and the Utility class is in another project than the resources I try to load, but they all get packaged into the same .jar ... – salbeira Mar 29 '14 at 20:21