Why is my URI not hierarchical?

JavaMavenJarJava 7Executable Jar

Java Problem Overview


I have files in resource folder. For example if I need to get file from resource folder, I do like that:

File myFile= new File(MyClass.class.getResource(/myFile.jpg).toURI());			   
System.out.println(MyClass.class.getResource(/myFile.jpg).getPath());

I've tested and everything works!

The path is

/D:/java/projects/.../classes/X/Y/Z/myFile.jpg

But, If I create jar file, using , Maven:

mvn package

...and then start my app:

java -jar MyJar.jar

I have that following error:

Exception in thread "Thread-4" java.lang.RuntimeException: ხელმოწერის განხორციელება შეუძლებელია
Caused by: java.lang.IllegalArgumentException: URI is not hierarchical
        at java.io.File.<init>(File.java:363)

...and path of file is:

file:/D:/java/projects/.../target/MyJar.jar!/X/Y/Z/myFile.jpg

This exception happens when I try to get file from resource folder. At this line. Why? Why have that problem in JAR file? What do you think?

Is there another way, to get the resource folder path?

Java Solutions


Solution 1 - Java

You should be using

getResourceAsStream(...);

when the resource is bundled as a jar/war or any other single file package for that matter.

See the thing is, a jar is a single file (kind of like a zip file) holding lots of files together. From Os's pov, its a single file and if you want to access a part of the file(your image file) you must use it as a stream.

Documentation

Solution 2 - Java

Here is a solution for Eclipse RCP / Plugin developers:

Bundle bundle = Platform.getBundle("resource_from_some_plugin");
URL fileURL = bundle.getEntry("files/test.txt");
File file = null;
try {
   URL resolvedFileURL = FileLocator.toFileURL(fileURL);
   
   // We need to use the 3-arg constructor of URI in order to properly escape file system chars
   URI resolvedURI = new URI(resolvedFileURL.getProtocol(), resolvedFileURL.getPath(), null);
   File file = new File(resolvedURI);
} catch (URISyntaxException e1) {
    e1.printStackTrace();
} catch (IOException e1) {
    e1.printStackTrace();
}

It's very important to use FileLocator.toFileURL(fileURL) rather than resolve(fileURL) , cause when the plugin is packed into a jar this will cause Eclipse to create an unpacked version in a temporary location so that the object can be accessed using File. For instance, I guess Lars Vogel has an error in his article - http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/

Solution 3 - Java

I face same issue when I was working on a project in my company. First Of All, The URI is not hierarichal Issue is because probably you are using "/" as file separator.

You must remember that "/" is for Windows and from OS to OS it changes, It may be different in Linux. Hence Use File.seperator .

So using

this.getClass().getClassLoader().getResource("res"+File.separator+"secondFolder")

may remove the URI not hierarichal. But Now you may face a Null Pointer Exception. I tried many different ways and then used JarEntries Class to solve it.

File jarFile = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
        String actualFile = jarFile.getParentFile().getAbsolutePath()+File.separator+"Name_Of_Jar_File.jar";
        System.out.println("jarFile is : "+jarFile.getAbsolutePath());
        System.out.println("actulaFilePath is : "+actualFile);
        final JarFile jar = new JarFile(actualFile);
	    final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
	    System.out.println("Reading entries in jar file ");
	    while(entries.hasMoreElements()) {
	    	JarEntry jarEntry = entries.nextElement();
	        final String name = jarEntry.getName();
	        if (name.startsWith("Might Specify a folder name you are searching for")) { //filter according to the path
	            System.out.println("file name is "+name);
	            System.out.println("is directory : "+jarEntry.isDirectory());
	            File scriptsFile  = new File(name);
	            System.out.println("file names are : "+scriptsFile.getAbsolutePath());
	         
	        }
	    }
	    jar.close();

You have to specify the jar name here explicitly. So Use this code, this will give you directory and sub directory inside the folder in jar.

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
QuestiongrepView Question on Stackoverflow
Solution 1 - JavarocketboyView Answer on Stackoverflow
Solution 2 - JavaIlya BuziukView Answer on Stackoverflow
Solution 3 - JavaPrateek MishraView Answer on Stackoverflow