I have a unit test package in which I keep a few txt files. These get loaded via getClass().getResource(file); call and it works just fine. I added into the same folder a csv file, and if I supply its name as the parameter i.e. getClass().getResource("csvFile.csv"); I get null... any ideas why?
When you use
getClass().getResource("csvFile.csv");
it looks relative to the class.
When you use
getClass().getClassLoader().getResource("csvFile.csv");
it looks in the top level directories of your class path.
I suspect you want the second form.
From Class.getResource(String)
Before delegation, an absolute resource name is constructed from the given resource name using this algorithm:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:
modified_package_name/name
Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').
As you can see the directory translation of the package name of the class is used.
For example, I have a maven project where the code is under src/main/java. My resources directory src/main/resources
I add csvFile.csv to my resources directory which will be copied to my class path.
public class B {
B() {
URL resource = getClass().getClassLoader().getResource("csvFile.csv");
System.out.println("Found "+resource);
}
public static void main(String... args) {
new B();
}
}
which prints
Found file:/C:/untitled/target/classes/csvFile.csv
This is in the area built by maven from the resources directory.
Have you tried getClass().getClassLoader().getResourceAsStream(file)
This in turn returns an inputstream which you can use to access the file
Related
For some reason I keep getting an NPE in a gradle javafx project.
My folder structure is very basic. I have a package with my java files in the main/java folder. I also have my resources in the main/resources folder. When I try to load image.png it gives me an NPE.
public static Image createImage(Object context, String url) {
Image m = null;
InputStream str = null;
URL _url = context.getClass().getResource(url);
try {
m = new Image(_url.getPath());
} catch (NullPointerException e) {
e.printStackTrace();
}
return m;
}
This is a helper class.
From the Scene I call: Image image = Helper.createImage(this, "image.png");
The absolute path to the image would be main/resources/images/image.png.
I checked every tutorial on the internet but I couldn't find any solution for this. I also tried it with the path to the image as parameter and also with an InputStream but it never worked.
Resources
The Class#getResource(String) and related API are used for locating resources relative to the class path and/or module path. When using Class to get a resource you can pass an absolute name or a relative name. An absolute name will locate the resource relative to the root of the class path/module path; an absolute name starts with a /. A relative name will locate the resource relative to the location of the Class; a relative name does not start with a leading /.
In a typical Maven/Gradle project structure, the src/main/java and src/main/resources are roots of the class path/module path. This means all resource names are relative to those directories. It's slightly more complicated than that because the files under those directories are moved to the target/build directory and it's that location that's put on the class path/module path, but for all intents and purposes consider the source directories as the root. There's a reason a get-resource API exists in the first place, to provide an application-location-independent way of obtaining resources.
Issues in Your Code
From your question I gather your project structure looks something like:
<project-dir>
|--src/
|--main/
|--java/
|--resources/
|--images/
|--image.png
And you're calling your method with an Object and a resource name of image.png. The problem here is that, since you're passing a relative name, the resource is located relative to the Class of the passed Object (i.e. context). I doubt your class is located in a package named images which means the resource will not be found relative to said class. You need to pass an absolute name: /images/image.png.
The other problem is your use of URL#getPath(). The URL you obtain from Class#getResource(String) will, if the resource were to be found, look something like this:
file:/path/to/gradle/project/build/resources/main/images/image.png
But the result of URL#getPath() will give you:
/path/to/gradle/project/build/resources/main/images/image.png
This causes a problem due to the way Image works. From the documentation:
All URLs supported by URL can be passed to the constructor. If the passed string is not a valid URL, but a path instead, the Image is searched on the classpath in that case.
Notice the second sentence. If the passed URL does not have a scheme then it's interpreted as a resource name and the Image will locate the image file relative to the classpath. In other words, since you're passing the value of URL#getPath() to the Image constructor it searches for the resource image.png in the package path.to.gradle.project.build.resources.main.images. That package does not exist. You should be passing the URL as-is to the Image constructor via URL#toString() or URL#toExternalForm().
Solution
If you're going to use the URL returned by Class#getResource(String) to load the Image then no matter what you need to use URL#toString() or URL#toExternalForm() instead of URL#getPath().
public static Image createImage(Object context, String resourceName) {
URL _url = context.getClass().getResource(resourceName);
return new Image(_url.toExternalForm());
}
Then you have at least two options:
Pass the absolute resource name (i.e. "/images/image.png") to your #createImage(Object,String) method since the image.png resource is not in the same package as the passed Object (i.e. context).
Move the resource to the same package as the class of the passed in Object (i.e. context). For instance, if the context object's class is com.foo.MyObject then place the resource under src/main/resources/com/foo and it will be in the same package as MyObject. This will allow you to continue passing the relative resource name.
Of course, as noted by the documentation of Image you can pass a scheme-less URL and it's interpreted as a resource name. In other words, you could do:
Image image = new Image("images/image.png");
And that should work. A note of caution, however: When using modules the above will only work if the resource-containing package is opens unconditionally or if the module itself is open.
Try using the path /images/image.png.
The resources always get referenced from the class root, in your case src/main/resources, so from there going to /images/image.png should be the correct path.
this is how I am passing the images in my application. ivSerialAssignmentLogo is a FXML element (ImageView).
ivSerialAssignmentLogo.setImage(new Image(getClass().getResourceAsStream("/img/serialAssignment.svg")));
In your case, you could use something like that
public static Image createImage(Object context, String url) {
Image m = null;
InputStream str = null;
URL _url = context.getClass().getResource("/images/" + url);
try {
m = new Image(_url.getPath());
} catch (NullPointerException e) {
e.printStackTrace();
}
return m;
}
I know this question has been asked several times but I still can't get it work by those solutions.
I have a maven project. And one Config.java file located in consumer/src/main/java. Here's the content:
import java.util.Properties;
public class Config {
Properties configFile;
public Config() {
configFile = new Properties();
try {
configFile.load(this.getClass().getClassLoader().
getResourceAsStream("property_table.config.txt"));
} catch(Exception e) {
e.printStackTrace();
}
}
public String getProperty(String key) {
String value = this.configFile.getProperty(key);
return value;
}
public static void main(String[] args) {
Config config = new Config();
System.out.println("URL: " + config.getProperty("URL"));
System.out.println("PASSWORD: " + config.getProperty("PASSWORD"));
}
}
I kept getting nullpointer exception. I know that's because it can't find the file property_table.config.txt.
At first I put the property_table_config.txt file in the same folder(consumer/src/main/java/) as Config.java file. And tried use /property_table_config.txt and 'property_table_config.txt`. Neither of them work.
And then I tried using absolute path, not working. And tried using /main/java/property_table_config, not working either.
Then I saw this solution: https://stackoverflow.com/a/2103625/8159477.
So I make a directory called resources and put it under main folder (i.e. the path of the folder is consumer/src/main/resources, and create a sub-folder config under resources. After putting the property_table_config.txt file there, I changed the code into this:
configFile.load(this.getClass().getClassLoader().getResourceAsStream("/config/property_table.config.txt"));
But this still didn't work. Can anyone give some hint on this? Any suggestions will be appreciated!!
According to Class.getResourceAsStream:
This method delegates to this object's class loader. If this object was loaded by the bootstrap class loader, the method delegates to ClassLoader.getSystemResourceAsStream.
Before delegation, an absolute resource name is constructed from the given resource name using this algorithm:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:
modified_package_name/name
Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').
This is how I understand the comments:
If you use ClassLoader.getResourceAsStream, send the absolute path from package root, but omitting the first /.
If you use Class.getResourceAsStream, send either a path relative the the current Class object (and the method will take the package into account), or send the absolute path from package root, starting with a /.
But in addition to this, you need to be cognizant of your build system. With maven, resource files are stored under src/main/resources.
So, in your case, I believe making the following changes should resolve the issue:
Put the file in src/main/resources.
Change the code to
this.getClass()
.getResourceAsStream("/property_table.config.txt")
//or `Config.class.getResource...
Alternatively, use
this.getClass().getClassLoader()
.getResourceAsStream("property_table.config.txt")`
I've tried this with a similar setup, and it works as expected.
ClassLoader().getResourceAsStream() is looking files only in classpath.
What you need is to have your config file in directory which is in classpath.
So, you have options:
when you run your java application from command line you can set path to directory in -cp parameter or CLASSPATH system variable. point there is: directory from where you need to get config file must be in class path - not a file. (e.g. if file location is c:\my_projects\test-project\config\my_config.properties and c:\my_projects\test-project\ is in classpath then getResourceAsStream call will be ClassLoader().getResourceAsStream("config/my_config.properties")
you can package your file into jar file and root of jar file is starting point for getResourceAsStream("config/my_config.properties")
If your Maven project is a jar project you need to use Maven resource plugin to put additional resource(s) into jar.
BTW: Maven does not put anything into jar file from src/main/java/ directory (if you do not explicitly specify it for resource plugin)
If you use IDE like Eclipse with your Maven project src/main/resources is a part of build classpath. Double check is it there and if it is not - do "Update Maven Project" or add it manually.
Still ClassLoader will see your properties file from src/main/resources folder only when you run project in IDE not from standalone Jar file - if you did not package your file or provide location in classpath.
hi can you try this one
String dirBase = new ClassPathResource("property_table.config.txt").getURI().getPath().replace("property_table.config.txt", "");
Can you try following code.
Config.class.getResourceAsStream("property_table.config.txt")
Update:
This is the code I tried.
package test;
import java.util.Properties;
public class Config
{
Properties configFile;
public Config()
{
configFile = new Properties();
try
{
configFile.load(Config.class.getResourceAsStream("property_table.config.txt"));
}
catch (Exception e)
{
e.printStackTrace();
}
}
public String getProperty(String key)
{
String value = this.configFile.getProperty(key);
return value;
}
public static void main(String[] args)
{
Config config = new Config();
System.out.println("URL: " + config.getProperty("URL"));
System.out.println("PASSWORD: " + config.getProperty("PASSWORD"));
}
}
And I placed property_table.config.txt file withn test package and it worked.
I have read many posts on here and done many Google searches but I am still unable to read a file from another java package within my current project.
In one of my classes I have the following code, however the input stream is always null. I have tried using the context class loader, as well as many other solutions but to no avail.
InputStream is = this.getClass().getResourceAsStream( "opcodes.txt" );
System.out.println(is);
Another attempt was:
InputStream is = ClassName.class.getResourcceAsStream("/resources/opcodes.txt");
which also returned null.
Any help or explanation for why I can not find the file within a resource package would be great.
p.s. I am using eclipse if that makes a difference.
EDIT: If I use an OpenFileDialog to find the file, I am able to open and read it, so the file does exist and is not corrupt.
The documentation of the getResourceAsStream() method, found here:
http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getResourceAsStream(java.lang.String)
says that:
"
Before delegation, an absolute resource name is constructed from the given resource name using this algorithm:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:
modified_package_name/name
Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').
"
Your first attempt would have succeeded had the resource been located within the same package as the one the class you're invoking the method from is located. Your second attempt fails because, like the documentation says, the name of the file you give ("/resources/opcodes.txt") is replaced by "resources/opcodes.txt". I guess it means that the method will now search for package resources WITHIN the package where the class that invokes the method is located and not outside of it. Since you don't have such an inner package, the method returns null.
A workaround would be to define a class within the package where your resource is located. That class could be empty for all you care. Just call:
ClassWithinResourcePackage.class.getResourceAsStream("opcodes.txt");
from within the class you currently invoke the method from, and it works.
I also tried to use the ".." syntax I know from command line, but it doesn't work. I think the documentation implies the method is looking for a file within the same package only.
Resource files are generally placed in src/main/resources/ directory in your project. These resources are also packed in the jar alongside the compiled class files with .class extension.
I have created a sample maven project with the directory hierarchy discussed above.
The resource file sample-resource.properties can be accessed in the program as below:
package temp;
import java.io.InputStream;
import java.util.Scanner;
public class ResourceTest {
public static void main(String[] args) {
InputStream inputStream = ResourceTest.class.getResourceAsStream("/sample-resource.properties");
Scanner scanner = new Scanner(inputStream);
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
}
}
This would read and print the contents of the resource file:
I am wondering why the method getResource keeps returning null, I have the following setup:
public static URL getResource(String path){
URL url = ResourceLoader.class.getResource(path);
if (Parameters.DEBUG){
System.out.println(path);
}
return url;
}
My project structure in Eclipse is as follows:
-- res
-- img
The path variable I pass to getResource has the value "/res/img" or "/res/img/smile.png". Yet the method keeps returning null and url is not set. I also followed the instructions of this question, which were to add the folder to the project's classpath via Run configurations, still without success... Does anyone know what I am doing wrong?
Short answer: Use "/img/smile.png".
What's actually happening is that any path starting with / which is given to the Class.getResource method is always treated as being relative to each entry in the classpath.
As your screenshot shows, the res directory is such a classpath entry. So the Class.getResource method treats the path you provide as relative to that entry. Meaning, relative to the res directory.
So, the method combines your string argument with that directory, which results in res/res/img/smile.png. Since no file (resource) exists at that location, it returns null.
http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getResource(java.lang.String)
The rules for searching resources associated with a given class are
implemented by the defining class loader of the class. This method
delegates to this object's class loader. If this object was loaded by
the bootstrap class loader, the method delegates to
ClassLoader.getSystemResource(java.lang.String). Before delegation, an
absolute resource name is constructed from the given resource name
using this algorithm:
If the name begins with a '/' ('\u002f'), then the absolute name of
the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:
modified_package_name/name Where the modified_package_name is the
package name of this object with '/' substituted for '.' ('\u002e').
I have the need to create an IFolder in an absolute location.
I usually have a class that does a "build" (or at least what I call a "build") for me in the workspace. The IFolder for the build-target-folder is returned by a method like this:
public IFolder getTargetFolder(IProject project){
return project.getFolder("build");
}
Now I created a subclass of this for the "deployment" (into a directory with absolute identifier). This subclass contains the same functionality but the getTargetfolder routine should be like this:
#Override
public IFolder getTargetFolder(IProject project){
IPath path = new Path("M:\\Path\\To\\My\\Deployment\\Directory\\");
IFolder target = project.getFolder(path);
return target;
}
However, I run into problems and I seem to not get a handle on the folder and an exception that says the folder (<ProjectRoot>/Path/To/My/Deployment/Directory) does not exist. How can I specify that this should not be a relative path?
The name given to project.getFolder() must be the name of a member folder (see the JavaDoc).
You cannot access a file or folder with the Resources API that lies outside of the workspace. If however the M:\\... path lies within a projects that is part of the workspace then you can resolve the folder through IWorkspaceRoot#getContainerForLocation()
For example:
IContainer container = project.getWorkspace().getRoot().getContainerForLocation( "M:\\..." );
The returned container can be either an IProject or an IFolder. But note that the returned container does not necessarily lies within the project.
Some more information can be found in Resources and the file system