72

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?

Lii
  • 11,553
  • 8
  • 64
  • 88
grep
  • 5,465
  • 12
  • 60
  • 112
  • 4
    You might take a look at this: http://stackoverflow.com/questions/10144210/java-jar-file-use-resource-errors-uri-is-not-hierarchical and the accepted answer. – cyroxx Aug 05 '13 at 10:01

3 Answers3

108

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

rocketboy
  • 9,573
  • 2
  • 34
  • 36
  • 11
    Is there a possibility to convert this into a java.io.File? – Sip Apr 13 '18 at 09:49
  • Well, I get the same error out a docker container but only when it runs in a k8s cluster. When running ins the IDE or in a docker container, I do not have the error. If this helps... – Erick Audet Jan 06 '21 at 23:36
  • 1
    What if I want to list the files in a directory, use their filenames, and read each file's text individually into java objects? – bonapart3 Jan 23 '21 at 01:30
  • I converted into a file with this: FileUtils.copyInputStreamToFile(inputStream, file); – Inanc Cakil Nov 28 '21 at 10:18
11

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/

Ilya Buziuk
  • 1,839
  • 5
  • 27
  • 43
  • 3
    Thank you, I owe you a beer for this one, indeed Vogella's article needs an update. – Vlad Ilie Oct 03 '14 at 12:10
  • http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fcore%2Fruntime%2FFileLocator.html This solution appears to be platform dependant. Is there a way to achieve something similar from IntelliJ without having to import "org.eclipse.core.runtime.FileLocator" ? – pwillemet Apr 23 '15 at 11:51
  • @Kwoinkwoin, yup this solution is for eclipse rcp plugin developers. I would recommend to try getResourceAsStream(...) approach – Ilya Buziuk Apr 23 '15 at 12:37
  • 1
    this solution is not platform independant – dasAnderl ausMinga Nov 11 '16 at 12:17
3

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.

JeanValjean
  • 17,172
  • 23
  • 113
  • 157
Prateek Mishra
  • 1,226
  • 10
  • 21
  • What if you change the packaging from jar to another compressed file implementation like zip? Will this work? What if you are building a library and users won't be using jar packaging? – bonapart3 Jan 23 '21 at 02:08