在ZIP文件中获取目录条目

6
我正在编写一个Java程序,它可以根据限定名称(例如:java.lang.String),从JDK的src.zip文件中提取并返回相应的条目以供进一步处理。
到目前为止,我的程序对于任何指向特定.java源文件的限定名称都可以正常工作;但是,当限定名称指向整个包(例如:java.util.*)时,我遇到了麻烦。在这种情况下,我希望我的程序返回给定包中所有条目的列表。
问题在于似乎没有一种(高效的)方式可以使用java.util.zip.*包中提供的实用程序来实现这样的操作!我已经尝试过ZipFile和ZipInputStream,但它们都无法识别src.zip文件中的目录!它们只返回单个.java源文件的条目!
在代码语言中,两者如下:
ZipEntry entry;
ZipInputStream zip = new ZipInputStream(new FileInputStream("src.zip"));
while((entry = zip.getNextEntry()) != null) 
    System.out.println(entry.isDirectory());

并且:

Enumeration<? extends ZipEntry> zip = new ZipFile("src.zip").entries();
while (zip.hasMoreElements()) {
    ZipEntry entry = zip.nextElement();
    System.out.println(entry.isDirectory());
}

始终返回 false,没有任何目录!

即使以下代码也是无用的,只会返回 null(表示未找到):

ZipFile zipfile = new ZipFile("src.zip");
zipfile.getEntry("java/util/");

一个解决方法是使用我上面列出的两种迭代方式之一,并对所需条目进行全面搜索。
if (entry.getName().startsWith("java/util/"))
    System.out.println(entry);

但很明显这并不高效!有没有办法从src.zip文件中检索目录条目,或有效地列出给定目录路径的条目?请注意,我想直接处理ZIP文件而不进行提取(由于明显的原因)。

更新

正如在Timothy Truckle的答案下讨论的那样,上述结果是使用此写作时最新的Oracle JDK中的src.zip文件实现的(即JDK-8 update-111)。当使用来自不同JDK版本(例如JDK-7 update-80)的其他src.zip文件时,结果会有所不同。感谢marabu在评论中指出的unzip -l实用程序。

注意

虽然解决了检索目录条目的问题,但仍未解决从ZIP文件的给定目录路径中有效地检索条目列表的问题。但是该案件仍已关闭,因为根据Timothy Truckle的答案,由于ZIP格式的限制,除了对条目进行穷举搜索外,无法以其他方式完成此操作。


据我所知,zip条目只是一堆完整路径“/foo/bar/lol/a.txt”等,而在这种情况下,您不一定需要“/foo/bar/lol/”、“/foo/bar/”、“/foo/”。因此,我认为您别无选择,只能迭代所有内容。 - user180100
@RC。所以你的意思是这与特定的src.zip文件有关?因为我见过其他ZIP文件中确实有目录条目。 - Seyed Mohammad
请参考https://dev59.com/tJrga4cB1Zd3GeqPmWzZ,了解似乎更为强大的执行此操作的方法。简而言之,检查“外部文件属性”字段是否存在标志0x10。 - Katie Kilian
1个回答

4
@RC。所以您的意思是它与这个特定的src.zip文件有关?因为我见过其他具有目录条目的ZIP文件。-Seyed Mohammad
不完全是,ZIP文件格式只知道文件而不知道目录。
您在其他zip文件中看到的可能是它们包含了一个名为“。”的零长度文件,用于每个(子)文件夹。但不是必需的也不是默认的。
但即使存在这些特殊条目,您也不能直接将它们作为ZIP中的文件夹处理(即使同一子文件夹中的所有文件都按顺序列出,也是偶然的,既不是必需的也不是暗示的)。

那么我想这就回答了我的问题:“我所要求的是ZIP格式的限制,而不是Java ZIP API的限制。因此,除了详尽搜索之外,没有其他解决方案。” 案子结案了。 - Seyed Mohammad
1
每个zip文件都包含所有必要的目录条目,以便重建文件系统结构,只要您不使用选项zip -D。使用unzip -l查找您的zip文件中是否存在目录条目。您可以通过尾部路径分隔符识别目录条目。 - marabu
@marabu 我检查了在 src.zip 文件上执行的 unzip -l 命令,它确实打印了一些目录的零长度条目;包括: java/net/java/lang/java/util/ 等等。然而正如我在问题中解释的那样,Java ZIP API 并没有检测到这些目录。那么这是什么意思呢? - Seyed Mohammad
@marabu 更正: 我在来自Oracle JDK-7u80的不同src.zip文件上测试了unzip -l命令,而最初的测试是在来自Oracle JDK-8u111的src.zip文件上进行的。运行上述Java代码在这个文件上也能找到目录条目!我想这确实与那个特定的src.zip文件有关!根据来自Oracle JDK-8u111的src.zip文件的unzip -l输出,没有零长度的目录条目,并且与Java ZIP API输出一致。 - Seyed Mohammad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接