Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my URI not hierarchical? [duplicate]

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?

like image 683
grep Avatar asked Aug 05 '13 09:08

grep


3 Answers

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

like image 191
rocketboy Avatar answered Nov 20 '22 00:11

rocketboy


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/

like image 11
Ilya Buziuk Avatar answered Nov 20 '22 02:11

Ilya Buziuk


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.

like image 2
Prateek Mishra Avatar answered Nov 20 '22 02:11

Prateek Mishra