Java access files in jar causes java.nio.file.FileSystemNotFoundException
JavaJava 7NioJava Problem Overview
While trying to copy some files in my jar file to a temp directory with my java app, the following exception is thrown:
java.nio.file.FileSystemNotFoundException
at com.sun.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:171)
at com.sun.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:157)
at java.nio.file.Paths.get(Unknown Source)
at com.sora.util.walltoggle.pro.WebViewPresentation.setupTempFiles(WebViewPresentation.java:83)
....
and this is a small part of my setupTempFiles
(with line numbers):
81. URI uri = getClass().getResource("/webViewPresentation").toURI();
//prints: URI->jar:file:/C:/Users/Tom/Dropbox/WallTogglePro.jar!/webViewPresentation
82. System.out.println("URI->" + uri );
83. Path source = Paths.get(uri);
the webViewPresentation
directory resides in the root directory of my jar:
This problem only exits when I package my app as a jar, debugging in Eclipse has no problems. I suspect that this has something to do with this bug but I'm not sure how to correct this problem.
Any helps appreciated
If matters:
I'm on Java 8 build 1.8.0-b132
Windows 7 Ult. x64
Java Solutions
Solution 1 - Java
A FileSystemNotFoundException
means the file system cannot be created automatically; and you have not created it here.
Given your URI, what you should do is split against the !
, open the filesystem using the part before it and then get the path from the part after the !
:
final Map<String, String> env = new HashMap<>();
final String[] array = uri.toString().split("!");
final FileSystem fs = FileSystems.newFileSystem(URI.create(array[0]), env);
final Path path = fs.getPath(array[1]);
Note that you should .close()
your FileSystem
once you're done with it.
Solution 2 - Java
Accepted answer isn't the best since it doesn't work when you start application in IDE or resource is static and stored in classes! Better solution was proposed at https://stackoverflow.com/questions/29746667/java-nio-file-filesystemnotfoundexception-when-getting-file-from-resources-folde/29747012#29747012
InputStream in = getClass().getResourceAsStream("/webViewPresentation");
byte[] data = IOUtils.toByteArray(in);
IOUtils is from Apache commons-io.
But if you are already using Spring and want a text file you can change the second line to
StreamUtils.copyToString(in, Charset.defaultCharset());
StreamUtils.copyToByteArray also exists.
Solution 3 - Java
This is maybe a hack, but the following worked for me:
URI uri = getClass().getResource("myresourcefile.txt").toURI();
if("jar".equals(uri.getScheme())){
for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
if (provider.getScheme().equalsIgnoreCase("jar")) {
try {
provider.getFileSystem(uri);
} catch (FileSystemNotFoundException e) {
// in this case we need to initialize it first:
provider.newFileSystem(uri, Collections.emptyMap());
}
}
}
}
Path source = Paths.get(uri);
This uses the fact that ZipFileSystemProvider internally stores a List of FileSystems that were opened by URI.
Solution 4 - Java
If you're using spring framework library, then there is an easy solution for it.
As per requirement we want to read webViewPresentation; I could solve the same problem with below code:
URI uri = getClass().getResource("/webViewPresentation").toURI();
FileSystems.getDefault().getPath(new UrlResource(uri).toString());