open resource with relative path in Java

JavaResourcesLoading

Java Problem Overview


In my Java app I need to get some files and directories.

This is the program structure:

./main.java
./package1/guiclass.java
./package1/resources/resourcesloader.java
./package1/resources/repository/modules/   -> this is the dir I need to get
./package1/resources/repository/SSL-Key/cert.jks    -> this is the file I need to get

guiclass loads the resourcesloader class which will load my resources (directory and file).

As to the file, I tried

resourcesloader.class.getClass().getResource("repository/SSL-Key/cert.jks").toString()

in order to get the real path, but this way does not work.

I have no idea which path to use for the directory.

Java Solutions


Solution 1 - Java

I had problems with using the getClass().getResource("filename.txt") method. Upon reading the Java docs instructions, if your resource is not in the same package as the class you are trying to access the resource from, then you have to give it relative path starting with '/'. The recommended strategy is to put your resource files under a "resources" folder in the root directory. So for example if you have the structure:

src/main/com/mycompany/myapp

then you can add a resources folder as recommended by maven in:

src/main/resources

furthermore you can add subfolders in the resources folder

src/main/resources/textfiles

and say that your file is called myfile.txt so you have

src/main/resources/textfiles/myfile.txt

Now here is where the stupid path problem comes in. Say you have a class in your com.mycompany.myapp package, and you want to access the myfile.txt file from your resource folder. Some say you need to give the:

"/main/resources/textfiles/myfile.txt" path

or

"/resources/textfiles/myfile.txt"

both of these are wrong. After I ran mvn clean compile, the files and folders are copied in the:

myapp/target/classes 

folder. But the resources folder is not there, just the folders in the resources folder. So you have:

myapp/target/classes/textfiles/myfile.txt

myapp/target/classes/com/mycompany/myapp/*

so the correct path to give to the getClass().getResource("") method is:

"/textfiles/myfile.txt"

here it is:

getClass().getResource("/textfiles/myfile.txt")

This will no longer return null, but will return your class. I hope this helps somebody. It is strange to me, that the "resources" folder is not copied as well, but only the subfolders and files directly in the "resources" folder. It would seem logical to me that the "resources" folder would also be found under "myapp/target/classes"

Solution 2 - Java

Supply the path relative to the classloader, not the class you're getting the loader from. For instance:

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();

Solution 3 - Java

In the hopes of providing additional information for those who don't pick this up as quickly as others, I'd like to provide my scenario as it has a slightly different setup. My project was setup with the following directory structure (using Eclipse):

Project/
src/                // application source code
org/
myproject/
MyClass.java
test/               // unit tests
res/                // resources
images/           // PNG images for icons
my-image.png
xml/              // XSD files for validating XML files with JAXB
my-schema.xsd
conf/             // default .conf file for Log4j
log4j.conf
lib/                // libraries added to build-path via project settings

I was having issues loading my resources from the res directory. I wanted all my resources separate from my source code (simply for managment/organization purposes). So, what I had to do was add the res directory to the build-path and then access the resource via:

static final ClassLoader loader = MyClass.class.getClassLoader();

// in some function
loader.getResource("images/my-image.png");
loader.getResource("xml/my-schema.xsd");
loader.getResource("conf/log4j.conf");

NOTE: The / is omitted from the beginning of the resource string because I am using [ClassLoader.getResource(String)][1] instead of [Class.getResource(String)][2].

[1]: http://download.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html#getResource%28java.lang.String%29 "Java API" [2]: http://download.oracle.com/javase/6/docs/api/java/lang/Class.html#getResource%28java.lang.String%29 "Java API"

Solution 4 - Java

When you use 'getResource' on a Class, a relative path is resolved based on the package the Class is in. When you use 'getResource' on a ClassLoader, a relative path is resolved based on the root folder.

If you use an absolute path, both 'getResource' methods will start at the root folder.

Solution 5 - Java

@GianCarlo: You can try calling System property user.dir that will give you root of your java project and then do append this path to your relative path for example:

String root = System.getProperty("user.dir");
String filepath = "/path/to/yourfile.txt"; // in case of Windows: "\\path \\to\\yourfile.txt
String abspath = root+filepath;



// using above path read your file into byte []
File file = new File(abspath);
FileInputStream fis = new FileInputStream(file);
byte []filebytes = new byte[(int)file.length()];
fis.read(filebytes);

Solution 6 - Java

For those using eclipse + maven. Say you try to access the file images/pic.jpg in src/main/resources. Doing it this way :

ClassLoader loader = MyClass.class.getClassLoader();
File file = new File(loader.getResource("images/pic.jpg").getFile());

is perfectly correct, but may result in a null pointer exception. Seems like eclipse doesn't recognize the folders in the maven directory structure as source folders right away. By removing and the src/main/resources folder from the project's source folders list and putting it back (project>properties>java build path> source>remove/add Folder), I was able to solve this.

Solution 7 - Java

resourcesloader.class.getClass()

Can be broken down to:

Class<resourcesloader> clazz = resourceloader.class;
Class<Class> classClass = clazz.getClass();

Which means you're trying to load the resource using a bootstrap class.

Instead you probably want something like:

resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()

If only javac warned about calling static methods on non-static contexts...

Solution 8 - Java

Doe the following work?

resourcesloader.class.getClass().getResource("/package1/resources/repository/SSL-Key/cert.jks")

Is there a reason you can't specify the full path including the package?

Solution 9 - Java

Going with the two answers as mentioned above. The first one

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();
resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()

Should be one and same thing?

Solution 10 - Java

In Order to obtain real path to the file you can try this:

URL fileUrl = Resourceloader.class.getResource("resources/repository/SSL-Key/cert.jks");
String pathToClass = fileUrl.getPath;    

Resourceloader is classname here. "resources/repository/SSL-Key/cert.jks" is relative path to the file. If you had your guiclass in ./package1/java with rest of folder structure remaining, you would take "../resources/repository/SSL-Key/cert.jks" as relative path because of rules defining relative path.

This way you can read your file with BufferedReader. DO NOT USE THE STRING to identify the path to the file, because if you have spaces or some characters from not english alphabet in your path, you will get problems and the file will not be found.

BufferedReader bufferedReader = new BufferedReader(
                        new InputStreamReader(fileUrl.openStream()));
               

Solution 11 - Java

I made a small modification on @jonathan.cone's one liner ( by adding .getFile() ) to avoid null pointer exception, and setting the path to data directory. Here's what worked for me :

String realmID = new java.util.Scanner(new java.io.File(RandomDataGenerator.class.getClassLoader().getResource("data/aa-qa-id.csv").getFile().toString())).next();

Solution 12 - Java

Use this:

resourcesloader.class.getClassLoader().getResource("/path/to/file").**getPath();**

Solution 13 - Java

One of the stable way to work across all OS would be toget System.getProperty("user.dir")

String filePath = System.getProperty("user.dir") + "/path/to/file.extension";

Path path = Paths.get(filePath);
if (Files.exists(path)) {
    return true;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGiancarloView Question on Stackoverflow
Solution 1 - JavaJohnnyView Answer on Stackoverflow
Solution 2 - Javajonathan.coneView Answer on Stackoverflow
Solution 3 - JavaE-richView Answer on Stackoverflow
Solution 4 - JavanbeyerView Answer on Stackoverflow
Solution 5 - JavaVikramView Answer on Stackoverflow
Solution 6 - JavaPaul MiraView Answer on Stackoverflow
Solution 7 - JavaTom Hawtin - tacklineView Answer on Stackoverflow
Solution 8 - JavaRichHView Answer on Stackoverflow
Solution 9 - Javamanocha_akView Answer on Stackoverflow
Solution 10 - JavaNiktoView Answer on Stackoverflow
Solution 11 - JavaAlferd NobelView Answer on Stackoverflow
Solution 12 - JavaOleg PoltoratskiiView Answer on Stackoverflow
Solution 13 - JavaQOPSView Answer on Stackoverflow