Intellij can't find .png - java

My intellij can't find local .png images.
private String craft = "craft.png";
ImageIcon ii = new ImageIcon(this.getClass().getResource(craft));
The .png is located in the same directory as the java files. I don't understand why it isn't working. Using maven build, tried alternating from resources to java, but still no luck :(

craft.png must be placed into src/main/resources, otherwise it will be not copied to the classpath according to the Maven rules. See this answer for more details.
Your code should be also changed to:
private String craft = "/craft.png";
Here is the sample working project.

Go to your IntelliJ Preferences and search for "resource patterns" (or just go straight to the "Compiler" settings).
IntelliJ will only copy certain resources to the output directory. Make sure the resource pattern includes *.png.
I have my resource pattern set to !*.java (copy everything that's not a source file) which seems to work fine (and should really be the default, in my opinion).

tried alternating from resources to java
So at first you tried putting craft.png into src/main/resources. That is where it must be put according to Maven (not in src/main/java).
But it didn't work because
this.getClass().getResource("craft.png") tries to find "craft.png" relative to the this.class's package. If your this.class is in package foo.bar then you must put craft.png in src/main/resources/foo/bar/
You can also provide an absolute path in getResource() by using a leading slash /. For example put craft.png into a custom folder under resources src/main/resources/customFolder/ and read it with the leading slash / in front of customFolder:
this.getClass().getResource("/customFolder/craft.png")
If you don't use leading slash in getResource() method then internally class's package name is prepended to the resource name to make it absolute.
This behavior is explained in Class.getResource()

Related

How to use relative path instead of absolute

So I need to set an icon for Intellij IDEA plugin, but when I'm trying to get this icon from my project with new File(relative path) or getClass().getResource(relative path). It can't find the files, only works with the absolute path. I have tried with the following relative paths:
images/icon.png
resources/images/icon.png
main/resources/images/icon.png
src/main/resources/images/icon.png
Icons path: src/main/resources/images/icon.png
Source code path: src/main/java/com/timetrack/plugin/MyClass.java
code:
File file = new File("src/main/resources/images/running.png");
BufferedImage img = ImageIO.read(file);
or with this
BufferedImage img = ImageIO.read(getClass().getResource("images/running.png"));
EDIT
Need to mention that I'am using Gradle to build the project. So the output directory looks like this:
Icon path: build/resources/main/images/icon.png
Compiled classes:
build/classes/java/main/com/timetrack/plugin/MyClass.class
Your resource string needs to start with a slash, since it is not in the same package as your class.
Paraphrased from the documentation of getResource:
If the name begins with a /, then the absolute name of the resource is the portion of the name following the /.
Otherwise, the absolute name is of the form modified_package_name/name, where the modified_package_name is the package name of this class with / substituted for ..
In other words, the argument passed to Class.getResource is assumed to be in the same package as the Class itself, unless the argument starts with a slash.
This is because the proper way to include resources in an application or library is to place them in the same package directory as the class that uses them. The reason for doing this is the same reason we use packages. For that matter, it’s the same reason applications don’t store all their files in the user’s home directory or in C:\: because there is a real risk that other programs will choose the same name and will interfere with your program.
Class.getResource searches the classpath for the requested resource. If you package your icon as images/running.png, and a library also decides to package its image as images/running.png, then Class.getResource will search the classpath and return whatever it finds first. Depending on the order of the classpath entries, either you will get the wrong image, or that other library will. The two are essentially stepping on each other.
On the other hand, if you place your image at src/main/resources/com/timetrack/plugin/running.png, it’s unlikely any other code will be using that package, so your odds of a collision are mimimal. And because this was intended to be the most common use case, using it this way is easier: You can retrieve the image URL with just MyClass.class.getResource("running.png").

Java getResource is in wrong path

I hope someone can help me here, becouse I'm fighting with a problem for some time. In my main class I use this command:
System.out.println(getClass().getClassLoader().getResource("org"));
The problem I've got is that it returns:
file:/E:/Tmp/ExamplePr/PROJEKT/proj/build/classes/java/main/org
instead of:
file:/E:/Tmp/ExamplePr/PROJEKT/proj/build/resources/java/main/org
The problem is that it goes into classes directory instead of resources dir. As a result I can't have access to my .fxml files I need. I'm using gradle for build and currently working with JavaFX. I've tried something like:
System.out.println(getClass().getClassLoader().getResource("/resources/java/main/org"));
But I just got null :(
Do you know any method to force him to use absolute path or to look for resources in resource filder or even use something like to use "../" from linux to go up. I dodn;t find any of this
The root of your resources tree is defined by the classloader (as described in the JavaDoc). You can define the root by explicitely setting it in your classpath or preferably by using a build tool like maven and following the conventions set and used by the tool. For maven projects the root would usually be at main/java/resources.
getResource will always return the first match in the class path. So if you specify E:/Tmp/ExamplePr/PROJEKT/proj/build/resources/java/main before E:/Tmp/ExamplePr/PROJEKT/proj/build/classes/java/main in your classpath, you will get what you want.
That said, the resources are usually meant to be copied with the classes, and sometimes both are packed in a jar file, so you shouldn't worry about it.
With JavaFX use FXMLLoader;
FXMLLoader.load(new URL(getClass().getResource("/fxml/myfxml.fxml").toExternalForm()));
Make sure to pass the platform appropriate separator and use a relative path.

Same code behaving differently on two different packaging

I have a set of codes which are common for two different products, but a part of the code is behaving differently for each product
URL wsdlURL = IntegrationLandscapeService.class.getClassLoader().getResource("IntegrationLandscapeService.wsdl");
For One set up it is giving absolute path and for the other its giving relative path and this is leading to problems, my requirement is to get absolute path for the issue.
Packaging:
Code flow:
The call is made from the Main Class File and from there CommonCode in common code it is looking for the WSDL located in LandScapeService.jar
Update:
The next line of the code is
IntegrationLandscapeService landscapeService = new IntegrationLandscapeService(wsdlURL);
but I get the below error
failed [Failed to access the WSDL at: jar:file:/
tracker.jar!/lib/t24-IF_IntegrationLandscapeService-IntegrationLandscapeService-jwc.jar!/IntegrationLandscapeService.wsdl
.It failed with:
\tracker.jar (The system cannot find the file specified).]
Screen Shot of Jar
The error shows two '!' in the path which indicates the resource is in an embedded/nested/inner jar-file. A product that uses the fat/bundled-jar approach (where one jar-file contains other jar-files) will need some trickery to load classes and resources from the embedded jar-files. You can read about it at http://www.jdotsoft.com/JarClassLoader.php (*)
In any case, there is not much you can do about it since loading resources from embedded jars is not supported natively by Java. The implementation providing the "trickery" I mentioned above will need to fix that (and some do it better than others, see the link above).
The other product with a Par-file indicates the use of OSGi which only requires proper configuration to keep resource-loading working. There is an answer here that explains your situation and solution options.
(*) Spring-boot also has some good documentation and a solution, but I have not tried using the solution with a non-Spring application. See https://docs.spring.io/spring-boot/docs/current/reference/html/executable-jar.html for more information.
You can use getAbsolutePath
File file = new File(url.getPath());
String path = file.getAbsolutePath();
Isn't that what you are looking for?
This is because the files inside the JAR are not treated as regular files, as they are not expanded and not available directly to file explorer.
In Jar, if the files are referred, you will get the path from the root of the JAR file.
Please make sure you have the classpath entry for the Jar location. This will help to find the resource. Otherwise, try the following code(not sure whether it will work in your case, give it a try).
String resource = "/com/example/IntegrationLandscapeService.wsdl"; //package structure of the file
URL res = IntegrationLandscapeService.class.getResource(resource);
Refer this answer to understand more Stack Overflow comment

Why my Jar doesn't run unless I extract files?

Every time I run the exported .jar file, that contains a JFrame with an image as its icon, the file doesn't run, unless I extract the file. In the compiler it is running. I dont want to make a launcher that saves both, the resources package and the jar file, in a directory.
"Why my Jar doesn't run unless I extract files?"
This seems to be the behavior of using File to your resources. Take for example
File file = new File("resources/image.png");
Image image = ImagIO.read(file);
And you project structure (Note the resources should actually be in the src, so that it builds into the jar automatically - unless you configure it differently. But for the sake of this argument, let's say you do confgigure it where resources is built to the jar)
C:\
Project
resources\image.png
Some examination:
Run from IDE - WORKS! Why? Using File looks for files on the file system. Using a relative path, the search will begin from the "working directory", which in the case of the IDE in generally the project root. So "resources/image.png" is a valid path, relative to ProjectRoot
Build jar, say it ends up in a dist dir in the project. This is what it looks like
ProjectRoot
dist
ProjectRoot.jar
Now for the sake of this argument (and is actually the correct way), let's try and print the URL of the resource in out program, so that when you run the jar, it prints out the URL of the file
URL url = Test.class.getResource("/resources/image.png");
System.out.println(url.toString());
When we run the jar C:\ProjectRoot\dist> java -jar ProjectRoot.jar We will see the print out C:\ProjectRoot\dist\ProjectRoot.jar!\resources\image.png. You can obviously see even though the current working directory is the location of the jar, the paths no longer match, with the added jar ProjectRoot.jar! location.
So why does it work when we extract it. Well when you extract it, then the path is correct
C:\ProjectRoot
dist
resources/image.png // from extracted jar
ProjectRoot.jar
When you run from the C:\ProjectRoot\dist >, the resource dir is where is should be.
Ok enough with the explanation.
For this reason, when you want to read embedded resources, they should be read from an URL as Andrew Thompson mentioned. This url should be relative to the class calling it, or the class loader. Here are a couple different ways:
As shown already
URL url = getClass().getResource("/resources/image.png");
Notice the /. This will bring us to the root of the classpath, where the resources dir will be. URL can be passed to many constructors, like ImageIcon(URL) or `ImageI.read(URL)
You can use:
InputStream is = getClass().getResourceAsStream("/resources/image.png");
Which will use an URL under the hood. You can use InputStream with many constructors also.
There's also ways to use the class loader, which will start at the root, so you don't need the /
URL url = getClass().getClassLoader().getResource("resources/image.png");
So there are a few ways you can go about it. But in general, reading File with hard coded string paths is never a good idea, when using embedded resources. It's possible to obtain the path dynamically so you can use File, but you will still need to use one of the aforementioned techniques, which unless you really need a File would be pointless, as you can do what you need with the InputStream or URL
To make a long story short
This would work
ProjectRoot
src\resources\image.png
URL url = getClass().getResource("/resources/image.png");
Image image = ImageIO.read(url);

Add images to jar

I want to set icon to my JFrame. I do the following:
Image icon = Toolkit.getDefaultToolkit().getImage("src/images/icon.jpg");
this.setIconImage(icon);
It works fine when I run this code from netbeans, but when I try to run this code from jar file, images are not shown in my JFrame. I have tried to load images as resources:
this.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/src/images/icon.jpg")));
but when I run this code it fails with NullPointerException
Uncaught error fetching image:
java.lang.NullPointerException
at sun.awt.image.URLImageSource.getConnection(URLImageSource.java:99)
at sun.awt.image.URLImageSource.getDecoder(URLImageSource.java:113)
at sun.awt.image.InputStreamImageSource.doFetch(InputStreamImageSource.java:240)
at sun.awt.image.ImageFetcher.fetchloop(ImageFetcher.java:172)
at sun.awt.image.ImageFetcher.run(ImageFetcher.java:136)
How can I do this work?
edit:
Thanks to all,
the problem was solved by specifying image as
Toolkit.getDefaultToolkit().getImage(getClass().getClassLoader().getResource("images/icon.JPG"))
As for it seems rather weird, and would be better if it was like
this.setIconImage(new ImageIcon(pathToIcon).getImage());
Assuming your JAR file has a top level directory called images, you can use either:
getClass().getResource("/images/icon.jpg") or
getClass().getClassLoader().getResource("images/icon.jpg")
Looking at the source code of URLImageSource, it appears that the reason that getConnection throws an NPE is that it has a null for the url. And that leads me to suspect that
getClass().getResource("/src/images/icon.jpg")
is returning null. It would do that if it could not locate a resource with that pathname.
I bet that the problem is that you've got the path wrong.
To prove / disprove this, you should run jar tvf on the JAR file, and look for the line that matches "icon.jpg". Is the corresponding pathname the same as what you are using? If not, use the pathname from the matching line in the getResource call and it should work. Alternatively, if the file doesn't show up at all, look at the NetBeans build configs that tell it what to put in the JAR file. (I'm not a NetBeans user, so I can't say where you would need to look ...)
If that leads you absolutely nowhere, another possibility is that getClass().getResource(...) is using a classloader that doesn't know about the JAR file containing the image. (This seems pretty improbable to me ...)
getResource() loads a resource from classpath, not an OS path, and the after compilation your classpath will not include the /src folder, but rather just its contents. So you'd better try /images/icon.jpg.
Also you may find this discussion somewhat useful.
This should do it assuming you can import javax.imageio.ImageIO:
Image icon = ImageIO.read(this.getClass().getResource("/src/images/icon.jpg"));
this.setIconImage(icon);
.."/src/images/icon.jpg"..
The '/src' prefix of the address seems suspicious. Many apps. will provide separate 'src' and 'build' directories, but it normally ends up that the 'src' prefix is not used in the resulting Jar. I recommend trying..
.."/images/icon.jpg"..
& also triple checking that the image is in the location of the Jar that the code is expecting to find it.
For this to work, you should access the images from a directory relative to some fixed class.
For example, if the image files are saved in a directory "images" on the same level as the Toolkit.class, then
this.setIconImage(Toolkit.getDefaultToolkit().getImage(Toolkit.class.getResource("images/icon.jpg")));
should work.
You can simply create a package inside the main source, and incluse your images in this package. Then, just call the images in your main class like:
ImageIcon a = new ImageIcon(MainClass.class.getResource("/Package/Image.jpg"));
JFrame f = new JFrame("Edit Configure File");
//Image image = ImageIO.read(getClass().getResource("images/ctx.Icon"));
f.setIconImage(new ImageIcon("images/ctx.PNG").getImage());//this works for me finally
//f.setIconImage(image);
//f.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("images/ctx.PNG")));

Categories

Resources