Java ImageIO.read(getClass().getResource()) returns null - java

The line
andImg = ImageIO.read(getClass().getResource("gate_and.png"));
fails with
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: input == null!
I'm using Eclipse and in the navigation view under the bin folder there is the file gate_and.png, suggesting that the file is in the build path.
In the package explorer view I have
project/src/view/class - This is the class that has the code above.
and
project/images/gate_and.png
I right clicked the project folder > build path > link source to add the images folder as a source, doing this again provides a confirmation msg that says images is already in the source.
I have also tried changing gate_and.png to images/gate_and.png and /images/gate_and.png, but since the image gate_and.png is in the bin folder, I think the original is correct.

Assuming your class is in package view.random.name, then
getClass().getResource("gate_and.png")
will look for the resource in
/view/random/name/gate_and.png
relative to the root of the classpath. You apparently don't have a resource by that name there.
By setting project/images as a build path entry, Eclipse will include everything in it on the classpath. Therefore, your resource will appear at
/gate_and.png
You can access it with
getClass().getResource("/gate_and.png")
Note the leading / that means start looking at the root of the classpath, ie. it's an absolute path.
All these rules are explained in the javadoc.

Related

Writing Images to ImageIcon in loop [duplicate]

The line
andImg = ImageIO.read(getClass().getResource("gate_and.png"));
fails with
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: input == null!
I'm using Eclipse and in the navigation view under the bin folder there is the file gate_and.png, suggesting that the file is in the build path.
In the package explorer view I have
project/src/view/class - This is the class that has the code above.
and
project/images/gate_and.png
I right clicked the project folder > build path > link source to add the images folder as a source, doing this again provides a confirmation msg that says images is already in the source.
I have also tried changing gate_and.png to images/gate_and.png and /images/gate_and.png, but since the image gate_and.png is in the bin folder, I think the original is correct.
Assuming your class is in package view.random.name, then
getClass().getResource("gate_and.png")
will look for the resource in
/view/random/name/gate_and.png
relative to the root of the classpath. You apparently don't have a resource by that name there.
By setting project/images as a build path entry, Eclipse will include everything in it on the classpath. Therefore, your resource will appear at
/gate_and.png
You can access it with
getClass().getResource("/gate_and.png")
Note the leading / that means start looking at the root of the classpath, ie. it's an absolute path.
All these rules are explained in the javadoc.

Java file path f.exists() always returns false

I'm trying to create a basic Java program that allows the user create files and folders.
I want all this to happen in a folder inside my project (image attached) so I've got some doubts...
This would be my proyect tree
Is the folder "Test" correctly placed? if not how do i access to it? As you see, it's inside com.company, should I move it to src?
When I try to check if exists, it says false.
This is my code:
public class Main {
Scanner input = new Scanner(System.in);
public static void main(String[] args) {
Main main = new Main();
main.init();
}
public void init(){
File f = new File("Test"); //Here i've tried "com"+File.separator+"company"+File.separator+"Test"
System.out.println(f.exists()); //output is false here
}
}
f.getParent() says null.
But when I try: System.out.println(f.getAbsolutePath()); it shows correctly the whole path.
The point of using relative path is because i'd like this code to work on ANY computer.
Thanks in advice, hope someone could help me a bit.
If you use relative pathnames in Java, they will be resolved relative to the running application's working directory. So you need to know what the working directory is going to be.
When you are launching an application in an IDE, the working directory depends on the IDE and the launcher configs. But it is typically the file system directory that corresponds to the top of the project.
Another thing to note is that the src folder you see is special. The entries in it are typically not files and directories. The are typically Java packages and classes. So in the file system, "src" > "com.company" > "Main" is actually represented as a file with the path "src/com/company/Main.java".
This means that it is kind of wrong to put arbitrary folders and files into the "src" folder. It will work ... but it is conceptually wrong. Data files don't belong in the source tree, and certainly not data files written by your application. (And when you start using a source control system, you will find that writing data files into your source tree is going to give you a headache. I won't go into details ... but I am pretty sure that you would regret it.)
The other thing that is conceptually wrong about what you are doing is that Java programs are normally written to be free standing things. The user of your program should not need to download and install Intellij or some other IDE and load your project into it. They will want to just run it from a JAR file. In that world, the project directory and the "src" folder won't exist, and hardwiring relative paths like "src/Test" will be problematic.
So lets ignore that for now and look at what your code is currently doing
Is the folder "Test" correctly placed? if not how do i access to it? As you see, it's inside com.company, should I move it to src?
According to the image, the Test folder (actually package) >>is<< in the src Folder.
When I try to check if exists, it says false.
Your code is using the wrong path. With the "Test" folder places where you have it (according to the picture!), the relative path should be "src/Test", not "Test" or "com/company/Test".
Note that Windows accepts either "/" or "\" will work as a file separator, even though "\" is what is used conventionally.
f.getParent() says null.
That is correct. The relative path "Test" does not have a parent part. It is a simple file / directory name.
Think of it this way. Until a File with a relative path is resolved, it is not determined what directory it is relative to.
But when I try: System.out.println(f.getAbsolutePath()); it shows correctly the whole path.
Again, correct.
When you call f.getAbsolutePath() on a relative File, the runtime system prepends the path of the application's working directory, and then gives you the result.
The point of using relative path is because I'd like this code to work on ANY computer.
That relative path will NOT work on ANY computer. You are using a path that is within your project's src tree, and your project typically won't exist on an end-user's computer. (See above.)
So what should you do?
There is no single correct answer.
You could put the file / directory into the user's current / working directory.
You could put the file / directory into the user's home directory, or a hidden subdirectory in the home directory. (This is a common approach on Linux.)
You could make the pathname for the directory a command line argument
You could get the pathname from an environment variable
You could get the pathname from an application specific config file.
The best answer will depend on the context.
According to your picture the path is wrong, you should check inside the src directory:
File f = new File("src/Test");
System.out.println(f.exists());

Whats the best way to specify a path to read from class-path even if project was a jar

I am trying to read a Properties file in a maven nature project using the Properties.load(); I am specifying a path as a string ex. "./someFolder/file.properties",
but when I try to use my project as dependency in other projects I am forced to copy those files to the other project , simply because the "." means current directory.
Is there a way to specify a path so it will always be valid despite where I am calling it from ? ,
I have tried using the MyClass.class.getClassLoader().getResourceAsStream() but I am having trouble using it , it worked sometimes and failed other times.
There are lots of misconceptions in your question.
"." means classPath
No. When used inside a filesystem path (i.e. a path passed to the constructor of a File, or FileReader, or FileInputStream), "." means the current directory.
When used in a resource path (i.e. passed to Class[Loader].getResource[AsStream]()), it's invalid.
The trick is to carefully read the documentation.
getResourceAsStream() expects a /-separated path.
When using ClassLoader.getResource[AsStream](), this path always starts from the root of the classpath. So you would pass a path looking exactly like a fully qualified class name, except the dots would be replaced by slashes. So, com/foo/bar.properties looks for a resource named bar.properties, in the package com.foo.
When using SomeClass.class.getResource[AsStream](), either the path starts with a /, and the path starts from the root of the classpath, or it doesn't, and it starts from the package of SomeClass. So, if SomeClass is in the package com.foo, using /com/foo/bar.properties is equivalent to using bar.properties.
It's hard to tell what you're doing wrong, since you're not providing any detail. But you really need to understand the difference between opening a file on the file system, and reading a resource loaded by the class loader. Sometimes, the resources just happen to be loaded by the class loader from the filesystem, because the classpath happens to contain directories, and not just jar files.
I noticed that my problem was that I had my properties files in the project path itself, and that the ClassLoader.getResource[AsStream](); looks is the target/classes folder, and that I didn't have the resources folder in my project.
I solved it my adding the resources folder to my build path and adding my files in the src/main/resources as the following src/main/resources/foo/bar.properties and loading it by SomeClass.class.getClassLoader().loadResourceAsStream("foo/bar.properties");.

Accessing a different folder using classloader

URL root = Thread.currentThread().getContextClassLoader().getResource(packageName.replace(".", "/"));
i use the above statement to access .class files given a package name. But in some cases i need to access the files from \build\test\classes instead of \build\classes. How do i modify the above statement?
You are having problems with your classpath.
${project}/build/test/classes and ${project}/build/classes folders suggest that you have either used Ant to compile your code, or checked "Allow output folders for source folders" option in Eclipse's "New Java Project" dialog.
You should configure you project to compile all source files into the same output folder, in your case /build/classes.
If you use classloader to load a resource the path you give it is not absolute to entire filesystem even if it starts with /.
InputStream is = this.getClass().getResourceAsStream("/some/resource");
This actually means find this file ${project}/build/classes/some/resource.
And in order to get that resource at the target location the easiest way is to place it in ${project}/src/some/resource.
Although you should consider using Maven and m2eclipse if your using Eclipse.

Java - class.getResource returns null

I am using the following to get the URL of this particular file, but it returns null. Does anyone have any suggestions as to the problem or an alternate way to do this?
URL url = ExchangeInterceptor.class.getResource("GeoIP.dat");
For those who use Intellij Idea: check for Settings > Build, Execution, Deployment > Compiler > Resource patterns.
The setting contains all extensions that should be interpreted as resources. If an extension does not comply to any pattern here, class.getResource will return null for resources using this extension.
The path is relative to the classpath root and if you don't give an absolute path, it is looking in the same package as the class you're using (in this case ExchangeInterceptor). To find something in the root use /GeoIP.dat.
Use the getResource method of the class' ClassLoader
URL url = ExchangeInterceptor.class.getClassLoader().getResource("GeoIP.dat");
I solved this problem by pointing out the resource root on IDEA.
Initially the directory was so and the icon was a plain folder icon
Before
Right click on a directory (or just the project name) -> Mark directory As -> Resource Root.
After
Recompile & rejoice :P
I've faced with the similar problem. From Java SE API for getResource​(String name) :
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
So I've added '/' before my directory : MyClass.class.getResource("/dir_name/").
In your case try to add '/' before your file name:
URL url = ExchangeInterceptor.class.getResource("/GeoIP.dat");
If you're using Gradle and IntelliJ, and changing Resource patterns didn't work, and your resource roots are set correctly...you can try this:
Settings > Build, Execution, Delpoyment > Build Tools > Gradle > Runner > Delegate IDE build/run actions to gradle. (IntelliJ 2017.3.3)
Source: https://youtrack.jetbrains.com/issue/IDEA-176738#comment=27-2518612
Just in case someone still has problems to understand that:
.getResource() grants you access to the local bin folder. That means, your resources need to be located in YourProject/bin/package/. The root folder is YourProject/bin/ and can be accssed by adding the prefix / to the String argument, like iirekm said.
No, that is the right way afaik. Make sure the resource is on your classpath. This is often the cause of these types of problems.
While using IntelliJ, I generated the project as a JavaFX app and then added maven framework support to it. Turns out, I then placed my resource in src/main/resources and had to add ./ behind every resource name that while using them in the code.
Also as stated in a previous answer, only loading the resource by a classLoader worked.
So for me, the final URL loading was done using:
URL url = getClass().getClassLoader().getResource(String.format(".%ssample.fxml", File.separatorChar));
The File.separatorChar returns / on *nix and \ on windows.
This is my example solution. Work for me.
The project structure:
• Source Packages
• game
• Game.java
• game.images
• tas_right.png
In the game class:
URL path=this.getClass().getClassLoader().getResource("images/tas_right.png")
Where do you have put this GeoIP.dat? In the same package as ExchangeInterceptor, or in the "root" package. If in the same package, your code is OK, if in the root - add '/' prefix.
Maybe you're using M2Eclipse? If configured incorrectly, it also may result in such problems. Another cause of such problems may be: misconfigured classloaders, misconfigured OSGi, ...
The file needs to be in the classpath, e.g.: -
bin/my/package/GeoIP.dat
The / prefix seems to be a lie. The following would work.
URL url = ExchangeInterceptor.class.getResource("my/package/GeoIP.dat");
I suspect the issue is that you do not have the file in the classpath.
I was able to fix it by adding "./" to the beginning of the file like this:
getClass().getClassLoader().getResource("./file.txt")
Instead of having the resource file in the same folder as your source files, create a resources folder parallel to the java source folder.
Before:
src
main
java
MyClass.java
file.bin
file.txt
After:
src
main
java
MyClass.java
resources
file.bin
file.txt
I use Intellij version Ultimate 2019.3
Go to
Settings -> Compiler -> Resource patterns.
Click ok.
Rerun Application/Server.
In my case, i included the jks in the project!
say you have :
titleLabel.setIcon(new ImageIcon(getClass().getResource("/uz/assets/icon.png")));//wrong !!
rightclick on the folder(mine is assets) an set Mark Directory as Resources
if you dont see that rightclick on project name and pickup Open module settings
Rightclick on resorces folder(assets in my case)
and select 'Resources'
Now go back to the above java instruction and remove path BUT leave /
like:
titleLabel.setIcon(new ImageIcon(getClass().getResource("/icon.png")));// correct one
A warning to all using the Path or Paths classes in Java: if you are on the god forsaken operating system known as Windows you will not be able to use Path.of or Paths.get as this will put backslashes in your path which Java will attempt to load and promptly fail. Instead use this:
Path.of(paths...).toString().replace(File.separator, "/")
You should always use this as it is OS independent. If anyone has a better or built in way please comment, I was unable to find one.
Strangely effective in my case (IJ 2022.1.4) was: close project (for example, quit IDEA), delete the /.idea folder completely (egg, rm -rd .idea), open project. When it re-imports the project, it runs as expected. Note: you loose about everything not included in gradle configs.
I realized using new File(location) works just fine in #dev and can also access files outside the /project folder
In case of eclipse.
Just a hint. Your code could be correct, but your jre configuration not. I ran into the the same error, nothing helped, until i checked the eclipse settings.
Make sure, that you set your execution environment right.
Preferences -> Java -> Installed JREs -> use "jdk..." as compatible JRE
First, you need to make sure you are accessing the right file on the right path. You can verify that by getClass().getResource("GeoIP.dat").getAbsolutePath().
Secondly, the path specifier is case-sensitive, so make sure your file is not named "geoIP.dat" or "GeoIP.DAT".

Categories