如果路径包含空格,则以 Zip 格式归档的 URI 不正确
URI to file in Zip incorrect if path contains spaces
我想获取 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
zip 的名称是
D:\example\name of zipfile.zip
我想知道 %2520
这似乎是 URL 编码的问题,但这不应该透明地处理吗?或者这是一个错误?
有解决这个问题的想法吗?
看起来像一个错误。
好像 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,因为路径实例 "knows" 它的文件系统。
只要您需要访问 zip 中的文件,就可以根据 Path 实例 (fileInZip.getFileSystem()
) 的信息创建一个新的文件系统。我没有详细说明,但至少文件存储应该包含再次访问 zip 文件所需的所有信息。有了这些信息,你可以调用类似 FileSystems.newFileSystem(Paths.get(fileStoreName), null)
的东西。
然后你也可以使用 Files.newInputStream(fileInZip)
来创建你的 InputStream
。此处无需使用 URI。
这只能用 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 shows that it had been fixed in JDK 9
with JDK-8131067 进行搜索。
我想获取 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
zip 的名称是
D:\example\name of zipfile.zip
我想知道 %2520
这似乎是 URL 编码的问题,但这不应该透明地处理吗?或者这是一个错误?
有解决这个问题的想法吗?
看起来像一个错误。
好像 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,因为路径实例 "knows" 它的文件系统。
只要您需要访问 zip 中的文件,就可以根据 Path 实例 (fileInZip.getFileSystem()
) 的信息创建一个新的文件系统。我没有详细说明,但至少文件存储应该包含再次访问 zip 文件所需的所有信息。有了这些信息,你可以调用类似 FileSystems.newFileSystem(Paths.get(fileStoreName), null)
的东西。
然后你也可以使用 Files.newInputStream(fileInZip)
来创建你的 InputStream
。此处无需使用 URI。
这只能用 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 shows that it had been fixed in JDK 9
with JDK-8131067 进行搜索。