After a long, arduous task of loading images using getResourceAsStream, I decided to organize all of my source code into packages within my src folder.
Since then, my original method of retrieving files no longer works.
Here is the original class I made:
package main;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ResourceLoader {
public static BufferedImage getImage(String uri) throws IOException {
BufferedImage image = null;
image = ImageIO.read(ResourceLoader.class.getResource(uri));
return image;
}
}
As mentioned previously, this worked 100% fine when entering the path:
"imgs/anims/testimage.png"
Worked perfectly fine with this. imgs is a folder within the source folder res.
We found your issue:
You used to load all of your images relatively to ResourceLoader which was located in the root package (discouraged!, and good that you refactored).
But now (You moved ResourceLoader from / to /main, and) all of your URIs point into "nirvana", since there are no imgs/... relatively to /main.
Solution:
refactor /imgs to /main/imgs according to ResourceLoader
Move imgs to main/imgs. (if main is (surely!) not there, please create it, this solution requires no code/uri adjustments.)
alternatively use absolute addressing
Refer to (all of) your images as /imgs/... (with a trailing slash character (/)).
alternatively refactor ResourceLoader back to /.
Also no further code/uri adjustments needed.
Related
Here's my code
The working directory for my program is printed at the bottom along with the error message, and on the left hand side of the screen my download png is located directly within my test project where the working directory is supposed to be. I have also tried using the direct file path of my download png within the getResource() method, but that didn't work either (I used double backslashes so that wasn't the issue).
package test;
import javax.swing.ImageIcon;
import javax.swing.Icon;
import java.io.File;
public class Test{
public Test() {
System.out.println(new File(".").getAbsolutePath());
ImageIcon download = new ImageIcon(getClass().getResource("download.png"));
}
public static void main(String[] args) {
new Test();
}
}
(Yes I know I didn't have to import Icon but I wanted to match what I had in the picture)
All I had to do was put the download.pgn file in the package where my class was located rather than the project that the absolute path was telling me to put it and the code worked. Hopefully this helps others who are having the same problem
I'm revisiting Java after briefly learning it in high school to work through the lwjgl git book. There's a section that kind of loses me where the fragment shader / vertex shader is supposed to be loaded, using the function 'getResourceAsStream'.
I've tried different approaches, and vainly tried to debug / print the locations where the JVM was searching for the file, but I'm kind of at a loss. I am very confused, but would also prefer understanding why this code doesn't work on my machine, and how to get it to work (with this package / class loading approach).
Since the classes both share the 'main' class, I thought the JVM would search starting there for a 'resources' folder. But this does not seem to be the case.
I do think it has to do with the package declarations, but I don't understand enough to proceed.
Here are the relevant files and locations... I tried to only include what I thought important.
// project-root/src/main/java/org/lwjglb/engine/Utils.java
package main.java.org.lwjglb.engine;
// other imports...
public class Utils {
public static String loadResource(String fileName) {
InputStream in = class.forName(Utils.class.getName()).getResourceAsStream(fileName);
// 'in' is null after this call
// other code...
}
}
// project-root/src/main/java/org/lwjglb/game/Renderer.java
import main.java.org.lwjgl.engine.Utils;
// other imports...
public class Renderer {
public void init() {
Utils.loadResource("/vertex.vs"); // fails
}
}
// project-root/src/main/resources/vertex.vs
// vertex shader code...
The issue is that the getResourceAsStream() call returns null, so the following code that depends on a valid result crashes with a java.lang.NullPointerException.
What path should I pass in to getResourceAsStream() so that it will not return null?
Assume the following directory structure:
|-- src
`-- test
|-- java
| `-- shaders
| `-- ShaderParser.java
`-- resources
`-- shaders
`-- fragmentShader.txt
The proper way to get the resource "fragmentShader.txt" from "ShaderParser.java" is:
Class clazz = Class.forName(TestUtils.class.getName());
InputStream in = clazz.getResourceAsStream("../../resources/shaders/fragmentShader.txt");
The ../ means "traverse upward one directory".
The path starts in the src/test/java/shaders/ directory so we use ../../ to traverse upward twice into src/test/ and then tack on the rest of our path resources/shaders/fragmentShader.txt.
It is important to remember that when using Class#getResourceAsStream(), it uses the package that the class resides in as the base directory. It ONLY uses relative paths because it is trying to load the resource using that class' ClassLoader. and will not work if supplied with a fully qualified path or a path starting at the project root.
Please refer to the documentation for more information.
I had erroneusly thought that Java had a reserved directory (e.g. 'resources') where it would look first to load files. Kind of similar to Flask in python.
However, I understand now that the class.getResourceAsStream() function either takes relative paths (to the current 'lowest' level package) or absolute paths (from the project's top-level root).
I had furthermore erroneously thought that I could try doing a relative path load, from one of the higher-level packages. As in, I'm in package main.java.org.lwjgl.engine.Utils, but when looking for the file main.resources.vertex.vs, I could start the search from the 'main' package and pass 'resources/vertex.vs' or 'resources/vertex.vs'. I don't know if this is possible, but it feels erroneous.
Instead, the solution is to pass the file location '/main/resources/vertex.vs'. This will start at the project-root, and correctly load the file.
I'm still confused as to how the lwjgl code worked, but I see that it could be possible that the classPath was set to 'main', so passing an absolute path could work.
I wanted to test having a program with a simple png image on it. I wrote a short program that does this, but I can't seem to get the path right. I have checked, checked again, rechecked, and quadruple checked my path name as to not get it right, but this image will not display, no matter what I do. I used a short class wrote by Oracle in the ImageIcon documentation (the creaetImageIcon()) to accomplish this, but it doesn't seem to help. I'll post the entire program below, as it is very short.
package practiceImages;
import java.awt.BorderLayout;
import java.awt.Toolkit;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ImageIconGUITest {
public static void main(String[] args) {
ImageIconGUITest gui = new ImageIconGUITest();
gui.display();
}
private ImageIcon createImageIcon(String path, String description) {
java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
private void display() {
JFrame frame = new JFrame();
JLabel label = new JLabel(createImageIcon(
"Users/Evan/javaItems/Sprites_and_Other_Art/green.png", "the color green"));
frame.add(BorderLayout.CENTER, label);
frame.setSize(500, 500);
frame.setVisible(true);
}
}
The getResource(String) method will only find resources that are on the run-time class-path of the application. Since this image seems like an application resource (i.e. supplied by you as part of the application) it should be put on the run-time class-path.
E.G. Most IDEs have a place you can put resources within the project structure, that will automatically be included at run-time. Move (or copy) the image to that path.
Then it becomes a matter of providing the correct String. Let us imagine your project is set up something like this:
bin
src
com
our
Application.java
resources
green.png
So Application.java is in package com.our;, while the image is in the path resources/green.png.
If accessing the image from the Application, the correct path would be (drum roll please..)
"/resources/green.png"
Notes
The leading / is important. It tells the JRE we want to look for the image from the 'root of the class-path', as opposed to using a path relative to the package of the class itself.
Correct case is also vital. A string of "/resources/green.png" will not locate an image named "/resources/Green.png" or "/resources/green.PNG".
Eclipse paths
Right click on the src directory, select Properties at the bottom of the menu.
Navigate (using the normal way you'd use without Eclipse) to the directory of the Location.
Then go to the parent directory.
You should see a bin directory that contains classes and (hopefully) the image.
Firstly, you've supplied a relative path, so the system is looking for the image relative to the location you executed the program.
Secondly, the path should have a drive spec or at least a leading /. Depending on your setup, something like 'C:/Users/Evan/javaItems/Sprites_and_Other_Art/green.png' should work (you may need to change the drive spec to meet your system)
Thirdly, make sure that the file exists in the specified location, System.out.println(new File("C:/Users/Evan/javaItems/Sprites_and_Other_Art/green.png").exists()) should return true, other wise the file is in the wrong location.
A relative path basically means a path location relative to the programs execution. So, if you were running the program from C:/Program Files/MyAwesomeApplication for example, a relative path of Users/Evan/javaItems/Sprites_and_Other_Art/green.png would become an absolute path of C:/Program Files/MyAwesomeApplication/Users/Evan/javaItems/Sprites_and_Other_Art/green.png. This describes the path from the root location to the file/folder in question.
You can test this by using System.out.println(new File("C:/Users/Evan/javaItems/Sprites_and_Other_Art/green.png").getAbsolutePath()) which will give you the full path.
Using this fixed it for me:
JButton btnBanana = new JButton("New button");
btnBanana.setIcon(new ImageIcon("D:\\Android\\Company\\images\\bananas-icon.png"));
use double slash instead of one , i had this problem and i fixed it . ill show you an example :
public Driver (){
ImageIcon us = new ImageIcon("C:\saeed.gif"); // OS cant find it
ImageIcon uk = new ImageIcon("C:\\saeed0.gif"); // OS can
JButton button = new JButton ("Click here " , us ) ;
button.setRolloverIcon(uk);
add(button);
}
To get the path of a image to a text filed, this code will help you
txtPath.setText(lblImage.getIcon().toString());
//txtPath is the text filed use todiplay the path
//lblImage is the label which shows the image
You need to do C:\\Test\\test.png and not C:/Test/test.png
I researched and looked into the PlayN game framework and I liked it a lot. I program in Scala and actually don't know Java but it's not usually a problem since they work together great.
I've set up a basic project in eclipse and imported all the libraries and dependencies. I even translated over the base maven project code. Here's the two files:
Zeitgeist.scala
package iris.zeit.core
import playn.core.PlayN._
import playn.core.Game
import playn.core.Image
import playn.core.ImageLayer
class Zeitgeist extends Game {
override def init (){
var bgImage: Image = assets().getImage("images/bg.png")
var bgLayer: ImageLayer = graphics().createImageLayer(bgImage)
graphics().rootLayer().add(bgLayer)
}
override def paint (alpha: Float){
//painting stuffs
}
override def update(delta: Float){
}
override def updateRate(): Int = {
25
}
}
Main.scala
package iris.zeit.desktop
import playn.core.PlayN
import playn.java.JavaPlatform
import iris.zeit.core.Zeitgeist
object Main {
def main(args: Array[String]){
var platform: JavaPlatform = JavaPlatform.register()
platform.assets().setPathPrefix("resources")
PlayN.run(new Zeitgeist())
}
}
The cool thing is it works! A window comes up perfectly. The only problem is I can't seem to load images. With the above line, "assets().getImage("images/bg.png")" it pops out
Could not load image: resources/images/bg.png [error=java.io.FileNotFoundException: resources/images/bg.png]
I've played around with the location of my resources file to no avail. I was even able to find bg.png myself with java.io.File. Am I doing something wrong? Is there something I'm forgetting?
Looking at the code of JavaAssetsManager, it looks like it is trying to load a resource and not a file. So you should check that your images are actually in the classpath and at the path you give ("resources/images/bp.png")
Alternatively, you can use getRemoteImage and pass a File URL. As you succeeded in using a java.io.File, you can just get the URL with method toUri of File (toUrl is deprecated).
This almost certainly doesn't work because you're doing this:
platform.assets().setPathPrefix("resources")
That means you're saying your source folder looks like this:
src/main/resources/resources/images/bg.png
src/main/resources/resources/images/pea.png
src/main/resources/resources/images
I imagine it actually looks like one of these:
src/main/resources/assets/images/bg.png <-- 'assets' the default prefix
src/main/resources/assets/images/pea.png
src/main/resources/assets/images
or:
src/main/resources/images/bg.png <-- You have failed to put a subfolder prefix in
src/main/resources/images/pea.png
src/main/resources/images
You can either do this, if you have no prefix:
plat.assets().setPathPrefix("")
Or just put your files in the assets sub-folder inside the resources folder.
It's worth noting that the current implementation calls:
getClass().getClassLoader().getResource(...)
Not:
getClass().getResource(...)
The difference is covered elsewhere, but the tldr is that plat.assets.getImage("images/pea.png") will work, but plat.assets.getImage("/images/pea.png") will not.
I'm working on a project that involves loading up a ResourceBundle. More explicitly, I've created a class that extends ListResourceBundle. The class is called Resources.java. It compiles fine and everything, but the MissingResourceException keeps popping up every time I try to load up the class:
All my source files are in package chapter31. When making this call with or without the "chapter31" in the string, always results in a MissingResourceException. My IDE is Eclipse. I've been playing around with this one problem for two days. I even tried changing the version of Eclipse. I'm at the end of my rope. What can I do in Eclipse to ensure that the getBundle() method can see the class. I don't know how it can miss it. It's in the same package! Please advise.
Alikas
package chapter31;
import java.applet.Applet;
import java.applet.AudioClip;
import java.util.ListResourceBundle;
import java.util.ResourceBundle;
import javax.swing.ImageIcon;
public class Resources extends ListResourceBundle {
Object contents[][];
public Resources() {
AudioClip clip = Applet.newAudioClip(getClass().getResource("/E31_10/audio/us.mid"));
ImageIcon image = new ImageIcon(getClass().getResource("/E31_10/image/us.gif"));
contents = new Object[3][2];
contents[0] = new Object[] {"clip", clip};
contents[1] = new Object[] {"icon", image};
contents[3] = new Object[] {"delay", new Integer(68000)};
}
protected Object[][] getContents() {
return contents;
}
public static void main(String[] args) {
ResourceBundle res = ResourceBundle.getBundle("chapter31.Resources");
}
}
The MissingResourceException is misleading here. Your problem may be caused by two other problems:
The resources in the following two lines cannot be found:
AudioClip clip =
Applet.newAudioClip(getClass().getResource("/E31_10/audio/us.mid"));
ImageIcon image = new ImageIcon(getClass().getResource("/E31_10/image/us.gif"));
If the first one is not the problem, there is a second problem:
You have a wrong array index contents[3] which will cause ArrayIndexOutOfBoundsException and this will also cause the misleading MissingResourceException to be thrown. If you can find this exception in your exception stack trace, your problem is here. Change it to contents[2] will solve the problem.
Note: The reason you are seeing MissingResourceException is ultimately caused by the class loader cannot create an instance of the Resources class due to the problems pointed out above. If you had put the contents array initialization codes in a separate method instead of the constructor, you may not get this exception at the object initialization phase. Of course, other exceptions will pop out later when you try to call getObject method.
Are you trying to load a message properties file called "chapter31.Resources"? If so then in Eclipse you can try the below:
Click on "Debug Configuration..."
Find the launcher you are using to execute the main method for Resources
Click on the Classpath tab
Click on "User Entries" and then Click the "Advanced" button
Select "Add External Folder" and choose the folder the "chapter31.Resources" .
ResourceBundle.getBundle() method is looking for the file in your classpath . if this file is not in your classpath it won't be able to find it.
The steps above adds the folder that "chapter31.Resources" to your classpath.
If this still does not work you can try passing the full path of the file to ResourceBundle.getResource().