如果路径包含空格,则 Zip 中文件的 URI 不正确

Posted

技术标签:

【中文标题】如果路径包含空格,则 Zip 中文件的 URI 不正确【英文标题】:URI to file in Zip incorrect if path contains spaces 【发布时间】:2016-06-21 06:00:35 【问题描述】:

我想获取 zip 文件条目的 URI,以便保留对其内容的引用,而不必保持 zip 文件打开。

因此我使用 zip 文件系统打开 zip 文件并将条目的路径导出为 URI。

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

现在我想再次读取文件,所以我尝试打开文件的流。

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

只要 zip 文件的路径不包含任何空格,它就可以工作。一旦它包含空格,我就会收到这样的错误

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

zip 中文件的 URI 是

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

压缩包的名称是

D:\example\name of zipfile.zip

我想知道%2520 这似乎是 URL 编码的问题,但不应该透明地处理吗?或者它是一个错误?

有解决这个问题的想法吗?

【问题讨论】:

【参考方案1】:

看起来像一个错误。

似乎com.sun.nio.zipfs.ZipPath.toUri() 要么搞砸了,要么我还没有阅读相应的 RFC ;-)。玩弄了一些其他的文件名。 zip 文件路径似乎有双重编码,但 zip 中的文件条目没有。 除了不使用 URI 方法之外,您还可以自己从头开始构建 URI,但是您不再那么灵活了。或者你只是撤消不必要的编码:

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

但老实说,我宁愿尝试省略 zip 文件的 URI,或者如果你真的必须,请事先重命名文件 ;-) 更好的是:如果它的行为与相应 RFC 中的规定不符,则打开一个错误.

您可能还想从以下有关错误等的问题中获得一些附加信息: Java 7 zip file system provider doesn't seem to accept spaces in URI

编辑(添加没有 URI 的提案):

您也可以尝试完全使用您的路径实例 (fileInZip) 而不是 URI,因为路径实例“知道”它的文件系统。 一旦您需要访问 zip 中的文件,您就可以根据 Path 实例 (fileInZip.getFileSystem()) 的信息创建一个新的 FileSystem。我没有详细说明,但至少文件存储应该包含再次访问 zip 文件所需的所有信息。有了这些信息,您可以拨打类似FileSystems.newFileSystem(Paths.get(fileStoreName), null) 的电话。 然后您也可以使用Files.newInputStream(fileInZip) 创建您的InputStream。此处无需使用 URI。

【讨论】:

它是相关的,但似乎是另一个问题。我从带有空格的路径创建 zipfs,并且当我使用 Java 8 时,帖子中提到的错误已修复。如果是错误,有什么解决方法吗?【参考方案2】:

这只能通过JDK 8 重现。以后的版本没有这个问题。 对于以下代码:

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

我通过JDK 1.8.0_212 得到以下输出:

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

JDK 11.0.3:

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

通过Java bug system 搜索表明它已在JDK 9 中修复为JDK-8131067。

【讨论】:

以上是关于如果路径包含空格,则 Zip 中文件的 URI 不正确的主要内容,如果未能解决你的问题,请参考以下文章

使用WebClient.DownloadData将URI空格转换为“%20”

PHP提取zip [重复]

路径部分中带有 // 的 URL 是不是有效?

在包含空间的路径中使用 jar 设置 mapreduce.job.jar

CLI 上的 NMake 宏定义,其中包含一个空格

如何从 URI 获取完整的文件路径