URI to file in Zip incorrect if path contains spaces

给你一囗甜甜゛ 提交于 2019-12-24 00:40:01

问题


I want to get the URIs to the entries of a zip file in order to keep references to it's contents without having to keep the zip file open.

Therefore I open the zip file using the zip filesystem and export the Path of the entries as URI.

Path zipfile = ...
URI uriOfFileInZip;
try(FileSystem fs = FileSystems.newFileSystem(zipfile, null)){
   Path fileInZip = fs.getPath("fileInZip.txt");
   uriOfFileInZip = fileInZip.toUri();
}

Now I want to read the file again, so I try to open a stream to the file.

InputStream is = uriOfFileInZip.toURL().openStream();

This works as long as the path of the zip file does not contain any spaces. As soon as it contains spaces, I get an error like this

java.io.FileNotFoundException: D:\example\name%20of%20zipfile.zip (The system cannot find the file specified)

the URI to the file in the zip is

jar:file:///D:/example/name%2520of%2520zipfile.zip!/fileInZip.txt

the name of the zip is

D:\example\name of zipfile.zip

I wonder about the %2520 this seems like an issue with the URL encoding, but shouldn't this be handled transparently? Or is it a bug?

Any ideas to solve this problem?


回答1:


Looks like a bug.

Seems as if com.sun.nio.zipfs.ZipPath.toUri() is either messed up, or I didn't read the corresponding RFC yet ;-). Played around with some other file names. There seems to be a double encoding going on for the zip file path, but not for the file entry in the zip. Besides not using the URI-approach you could also build the URI yourself from scratch, but then you are not that flexible anymore. Or you just undo the unnecessary encoding:

String uriParts[] = uriOfFileInZip.toString().split("!");
uriParts[0] = URLDecoder.decode(uriParts[0], "UTF-8");
uriOfFileInZip = URI.create(String.join("!", uriParts));

But to be honest, I would rather try to omit the URI for zip files or if you really have to, rename the files beforehand ;-) Better yet: open a bug if it does not behave as stated in the corresponding RFCs.

You may also want to get some additional information from the following question regarding bug, etc.: Java 7 zip file system provider doesn't seem to accept spaces in URI

EDIT (added proposal without URI):

You can also try to completely work with your Path instance (fileInZip) instead of the URI, as the path instance "knows" its filesystem. As soon as you need access to the file inside the zip, you create a new FileSystem based on the information of the Path instance (fileInZip.getFileSystem()). I did not elaborate that completely, but at least the file store should contain all the necessary information to access the zip file again. With that information you could call something like FileSystems.newFileSystem(Paths.get(fileStoreName), null). Then you can also use Files.newInputStream(fileInZip) to create your InputStream. No need to use URI here.




回答2:


This is only reproducible with JDK 8. The later versions do not have this issue. For the following code:

Map<String, String> env = new HashMap<>(); 
env.put("create", "true");
final FileSystem fs = FileSystems.newFileSystem(new URI("jar:file:/D:/path%20with%20spaces/junit-4.5.jar"), env);
System.out.println(fs.getPath("LICENSE.TXT").toUri()); `

I got the following output with JDK 1.8.0_212 :

jar:file:///D:/path%2520with%2520spaces/junit-4.5.jar!/LICENSE.TXT 

whereas with JDK 11.0.3:

jar:file:///D:/path%20with%20spaces/junit-4.5.jar!/LICENSE.TXT

A search through the Java bug system shows that it had been fixed in JDK 9 with JDK-8131067 .



来源:https://stackoverflow.com/questions/37936627/uri-to-file-in-zip-incorrect-if-path-contains-spaces

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!