Pergunta

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!/...)

Foi útil?

Solução

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

Outras dicas

"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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top