Java load all resources

How to Load Resources from Classpath in Java with Example

Classpath in Java is not only used to load .class files, but also can be used to load resources e.g. properties file, images, icons, thumbnails, or any binary content. Java provides API to read these resources as InputStream or URL. Suppose, you have a properties file inside config folder of your project, and you want to load that properties file, how do you do that? Similarly, you have icons and thumbnails for your web applications on icons directory of your project, how do you load them? Answer is by using java.lang.Class’getResource() and getResourceAsStream() method. These method accepts path of resource as String and returns URL and InputStream respectively. You can obtain a reference of Class by calling either getClass() method or by using class literal. If you have an object, then you can call getClass() because its a non-static method, on the other hand, if you don’t have any object, you can simply use .class with name of any class e.g. Sample.class will give you reference of java.lang.Class. These methods are available from JDK 1.1 and you can even use them anywhere you have access to core Java library. If you are creating J2ME games or application, you can use these method to load icons and tiles for your game, and all other resource for your application as well.

Читайте также:  Php автоматически открыть файл

How does getResourceAsStream works

Internally this method delegate the loading request of resource to its class loader. If you call getResourceAsStream() method on an object which is loaded by BootStrap ClassLoader then it will delegate it to ClassLoader.getSystemResourceAsStream(java.lang.String) method. We pass path of resource to this method but rules for searching resources associated with a given class are implemented by the defining class loader of the class. Since you can pass both absolute and relative path to Class.getResourceAsStream(), but ClassLoader.getResourceAsStream() takes an absolute path, that’s why an absolute resource name is constructed from the given resource name using following 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 means, the resource name passed to the method should look like /com/abc/config/app.properties if the app.properties is stored in the com.abc.config package instead of the current class’s.

If you look at the code of java.lang.Class in Eclipse IDE by using short-cut Ctrl+T and typing java.lang.Class, you can see how this method works :

public InputStream getResourceAsStream(String name) < name = resolveName(name); ClassLoader cl = getClassLoader0(); if (cl==null) < // A system class. return ClassLoader.getSystemResourceAsStream(name); >return cl.getResourceAsStream(name); >

This algorithm is implemented at resolveName() method, as seen below :

/** * Add a package name prefix if the name is not absolute Remove leading "/" * if name is absolute */ private String resolveName(String name) < if (name == null) < return name; >if (!name.startsWith("/")) < Class c = this; while (c.isArray()) < c = c.getComponentType(); >String baseName = c.getName(); int index = baseName.lastIndexOf('.'); if (index != -1) < name = baseName.substring(0, index).replace('.', '/') +"/"+name; >> else < name = name.substring(1); >return name; >

loading resources from classpath in Java

Main problem comes while loading resource using getResourceAsStream() method is NullPointerException, because this method return null if its not able to find the resource. In following example, we have a Eclipse project, and I have created a properties file called app.properties inside config directory. Now to load that file, I just need to pass “app.properties”, if I pass anything like “config/app.properties” or “/config/app.properties” getResourceAsStream() will return null, and code will subsequently throw NullPointerException as shown below :

Exception in thread "main" java.lang.NullPointerException at java.util.Properties$LineReader.readLine(Unknown Source) at java.util.Properties.load0(Unknown Source) at java.util.Properties.load(Unknown Source) at Test.main(Test.java:29)

to avoid this error you must check output of getResourceAsStream() before using it, defensive programming is there just because of this kind of methods.

Java Program to load Resource from Classpath

Here is our complete Java program to load images, resources, text file or binary file from classpath in Java, resource can be anything, what is important is that it must be accessible.

package test; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Properties; /** * Java Program to demonstrate how to load resources e.g. properties file from * classpath. There are two ways to load resources in Java, one by using * getResourceAsStream() and getResource() method from java.lang.Class. Main * difference between these two methods are that one returns an InputStream * while other returns a URL object. * * @author Javin Paul */ public class ResourceLoader < public static void main(String args[]) < // loading resource using getResource() method InputStream in = Test.class.getResourceAsStream("app.properties"); Properties config = new Properties(); try < config.load(in); System.out.println(config.getProperty("name")); System.out.println(config.getProperty("version")); >catch (IOException e1) < e1.printStackTrace(); >// loading resource using getResourceAsStream() method URL resourceURL = Test.class.getResource("app.properties"); Properties appConfig = new Properties(); try < appConfig.load(resourceURL.openStream()); System.out.println(appConfig.getProperty("name")); System.out.println(appConfig.getProperty("version")); >catch (IOException e) < e.printStackTrace(); >> > Output: SampleApp 1.0.0 SampleApp 1.0.0

If you look closely you will find that we have used both getResource() and getResourceAsStream() method to load resource from classpath in Java, in this case just properties file. First example looks more cleaner than second example because we don’t need to open an explicit stream, getResourceAsStream() method returns an InputStream, which can be used anywhere. That’s all on how to load resources from class-path in Java.

Источник

gkhays / ListResources.java

The problem started when I attempted to pass what I thought was a valid relative path to a J2EE test method. I mistakenly thought the unqualified file name or the unqualified file name with a leading slash would suffice. It did not. The solution ended up being the file name prefixed with the resource path, in this case:

A quick way to figure out the resource path.

System.out.printf("Resource Path: %s\n", ListResources.class .getResource("").getPath());

Output: Resource Path: /C:/Users/gkh/gist/bin/org/gkh/

Next, get the path of the currently running Java program.

ClassLoader loader = ListResources.class.getClassLoader(); System.out.printf("Resource: %s\n", loader.getResource("org/gkh/ListResources.class"));

Whereas the system property java.class.path shows what would be passed with the -cp or -classpath switch .

System.out.printf("Class Path: %s\n", System.getProperty("java.class.path"));

Class Path: C:\Users\gkh\gist\bin;C:\Users\gkh\lib\jackson-core-2.4.4.jar;C:\Users\gkh\gist\lib\jaxen-1.1.6.jar;.

A resource is a URL . Note: In JAVA EE, you would use a leading slash, e.g. «/a.txt» .

URL url = ListResources.class.getResource("a.txt"); System.out.println(url.getFile());

Output: Resource URL: /C:/Users/gkh/gist/bin/org/gkh/a.txt

Using the Context Class Loader

EnumerationURL> resources = Thread.currentThread() .getContextClassLoader().getResources("org/gkh"); while (resources.hasMoreElements()) < URL url1 = resources.nextElement(); System.out.printf("Resource URL: %s\n", url1); Scanner scanner = new Scanner((InputStream)url1.getContent()); String s = scanner.useDelimiter("\\A").next(); System.out.printf("Resource Content: %s\n", s); scanner.close(); >
Resource URL: file:/C:/Users/haysg/Development/WorkBench/Snippets/Snippets/bin/org/gkh Resource Content: a.txt ListResources.class ListThreads.class ListThreads$1.class Log4jExample.class 

FileInputStream with Relative Path

It is possible to create a FileInputStream using a relative path, the key is to remember that not only must you specify the root of the class path but also the package scope. A helpful article in this regard is FileInputStream doesn’t work with the relative path. In particular, see the responses from Michael and BackSlash.

private String inputStreamToString(InputStream in) < Scanner scanner = new Scanner(in); String contents = scanner.useDelimiter("\\A").next(); scanner.close(); return contents; > InputStream is = new FileInputStream("bin/org/gkh/a.txt"); String contents = inputStreamToString(is);

You cannot directly load a URL with a path name, with or without a leading slash. In this case, the code will throw a FileNotFoundException .

URL fileURL = new URL("file:/" + resourceName); fileURL.getContent();

Whereas URL fileURL = new URL(resoureName) will throw a MalformedURLException .

When loaded with class.getResource , the contents of the resource are created as a plain text input stream.

URL url2 = ListResources.class.getResource(resourceName); System.out.println(url.getContent());

Output: sun.net.www.content.text.PlainTextInputStream@2f92e0f4

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

package org . gkh ;
import java . io . File ;
import java . io . FileInputStream ;
import java . io . IOException ;
import java . io . InputStream ;
import java . net . URL ;
import java . util . Enumeration ;
import java . util . Scanner ;
public class ListResources
public static String inputStreamToString ( InputStream in )
Scanner scanner = new Scanner ( in );
String contents = scanner . useDelimiter ( » \\ A» ). next ();
scanner . close ();
return contents ;
>
public static void main ( String [] args ) throws IOException
System . out . printf ( «Resource Path: %s \n » , ListResources . class
. getResource ( «» ). getPath ());
ClassLoader loader = ListResources . class . getClassLoader ();
System . out . printf ( «Resource: %s \n » ,
loader . getResource ( «org/gkh/ListResources.class» ));
System . out . printf ( «Class Path: %s \n » ,
System . getProperty ( «java.class.path» ));
// Note: In JAVA EE, you would use a leading slash.
URL url = ListResources . class . getResource ( «a.txt» );
System . out . printf ( «Resource URL: %s \n » , url . getFile ());
System . out . println ( «Using the Context Class Loader» );
Enumeration < URL >resources = Thread . currentThread ()
. getContextClassLoader (). getResources ( «org/gkh» );
while ( resources . hasMoreElements ())
URL url1 = resources . nextElement ();
System . out . printf ( «Resource URL: %s \n » , url1 );
Scanner scanner = new Scanner (( InputStream ) url1 . getContent ());
String s = scanner . useDelimiter ( » \\ A» ). next ();
System . out . printf ( «Resource Content: %s \n » , s );
scanner . close ();
>
String resourceName = «a.txt» ;
URL url2 = ListResources . class . getResource ( resourceName );
InputStream in = ListResources . class . getResourceAsStream ( resourceName );
// sun.net.www.content.text.PlainTextInputStream@2f92e0f4
System . out . println ( url . getContent ());
String contents = inputStreamToString ( in );
System . out . printf ( «The contents of [%s]: %s \n » , resourceName , contents );
InputStream is = new FileInputStream ( «bin/org/gkh/a.txt» );
contents = inputStreamToString ( is );
>
>

Источник

Оцените статью