Java Jar file: use resource errors: URI is not hierarchical
Solution 1
You cannot do this
File src = new File(resourceUrl.toURI()); //ERROR HERE
it is not a file! When you run from the ide you don't have any error, because you don't run a jar file. In the IDE classes and resources are extracted on the file system.
But you can open an InputStream
in this way:
InputStream in = Model.class.getClassLoader().getResourceAsStream("/data.sav");
Remove "/resource"
. Generally the IDEs separates on file system classes and resources. But when the jar is created they are put all together. So the folder level "/resource"
is used only for classes and resources separation.
When you get a resource from classloader you have to specify the path that the resource has inside the jar, that is the real package hierarchy.
Solution 2
If for some reason you really need to create a java.io.File
object to point to a resource inside of a Jar file, the answer is here: https://stackoverflow.com/a/27149287/155167
File f = new File(getClass().getResource("/MyResource").toExternalForm());
Solution 3
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 4
I got a similiar issues before, and I used the code:
new File(new URI(url.toString().replace(" ","%20")).getSchemeSpecificPart());
instead of the code :
new File(new URI(url.toURI())
to solve the problem
hqt
Those who don't speak math are doomed to speak nonsense. My brief profile: https://github.com/hqt/profile
Updated on July 05, 2022Comments
-
hqt almost 2 years
I have deployed my app to jar file. When I need to copy data from one file of resource to outside of jar file, I do this code:
URL resourceUrl = getClass().getResource("/resource/data.sav"); File src = new File(resourceUrl.toURI()); //ERROR HERE File dst = new File(CurrentPath()+"data.sav"); //CurrentPath: path of jar file don't include jar file name FileInputStream in = new FileInputStream(src); FileOutputStream out = new FileOutputStream(dst); // some excute code here
The error I have met is:
URI is not hierarchical
. this error I don't meet when run in IDE.If I change above code as some help on other post on StackOverFlow:
InputStream in = Model.class.getClassLoader().getResourceAsStream("/resource/data.sav"); File dst = new File(CurrentPath() + "data.sav"); FileOutputStream out = new FileOutputStream(dst); //.... byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { //NULL POINTER EXCEPTION //.... }
-
hqt about 12 yearsI have tried again your way (is my second code above), but when it is go through:
in.read(buf)
---> I meet null point exception. :( @:resource is a folder in my project. it has same hierarchy with other package. So, I need I must includeresource
-
dash1e about 12 yearspost the hierarchy of your project
-
TekTimmy over 11 yearsBut what if i really NEED an "File" object... ?
-
dash1e over 11 yearsYou cannot have a File object because a resource is not necessary a file.
-
Zarathustra over 10 yearsCould you please provide more details on that? When is a ressource not a file?
-
dash1e over 10 yearsWhen the resource is located in a jar, for example, the single
resource
is a Jar Entry object (not a file on file system), and cannot be used to create an instance ofjava.io.File
class -
Ilya Buziuk almost 10 years@dash1e ^ This is not true - see my answer
-
Andrey about 9 yearsWhat is Platform class? Some non-rt library needed?
-
Ilya Buziuk about 9 years@AndreyP this solution is for eclipse rcp plugin developers. I would recommend to try getResourceAsStream(...) approach
-
Daniel about 9 yearsit works for me without the slash: "data.sav" instead of "/data.sav"
-
dash1e about 9 years@Daniel it depends on where you put your resource. You can use
data.sav
without the starting/
if you put your resource file in the same package of your class file. But in the question thedata.sav
is in the root package so in that case he needs to prepend/
. -
J. Katzwinkel about 8 yearsIn my maven-built RCP E4 application, jar-bundled binary files need to be extracted and opened. Your solution finally enabled me to do so and open
file.getAbsolutePath()
in the OS default browser. -
JN Gerbaux over 7 yearsJust like TekTimmy: But what if I REALLY NEED a file ? I'm in a email sending process and we wanna join a logo file picture to email. The pict is in the jar and I have to give it to the datasource as a File, not an InputStream...
-
Rémi about 3 yearsThanks ! This answer was very helpful, since I got a bug with FileLocator.resolve. I could create the File object directly with :
File f = new File(FileLocator.toFileURL(resolvedFileURL).toURI());
-
Vishal Patel almost 3 years@JNGerbaux i also wanted a
File
object so i created tempFile
and copied content fromInputStream
to File object. usingFileUtils.copyInputStreamToFile(inputStream, file);