Java access files in jar causes java.nio.file.FileSystemNotFoundException

JavaJava 7Nio

Java 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:

enter image description here

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());

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
Questiontom91136View Question on Stackoverflow
Solution 1 - JavafgeView Answer on Stackoverflow
Solution 2 - JavaKinmaruiView Answer on Stackoverflow
Solution 3 - Javafuemf5View Answer on Stackoverflow
Solution 4 - JavahemantoView Answer on Stackoverflow