See also: Read a File from Disk into a String.
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:
target/test-classes/test.txt
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"));
Resource: file:/C:/Users/haysg/Development/WorkBench/Snippets/Snippets/bin/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"));
Output:
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
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();
}
Output:
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
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