在Java中直接读取Zip文件中的文件

6

我的情况是我有一个包含一些文件(txt、png等)的zip文件,并且我想通过它们的名称直接读取它们,我已经尝试了以下代码,但没有结果(空指针异常):

InputStream in = Main.class.getResourceAsStream("/resouces/zipfile/test.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));

resources是一个包,而zipfile则是一个压缩文件。


是的,那绝对行不通。 - Perception
1
你需要使用java.util.zip。http://docs.oracle.com/javase/6/docs/api/java/util/zip/package-summary.html - gefei
1
压缩文件是否在类路径上?它需要在那里。 - chrislhardin
@chrislhardin:你说得对,如果我将 zipFile.zip 添加到类路径中,它就可以正常工作,所以这也是一个解决方案(+1)。 - Adil
3个回答

17

如果您可以确定您的zip文件永远不会被打包到另一个jar文件中,那么您可以使用以下代码:

URL zipUrl = Main.class.getResource("/resources/zipfile.zip");
URL entryUrl = new URL("jar:" + zipUrl + "!/test.txt");
InputStream is = entryUrl.openStream();

或者:

URL zipUrl = Main.class.getResource("/resources/zipfile.zip");
File zipFile = new File(zipUrl.toURI());
ZipFile zip = new ZipFile(zipFile);
InputStream is = zip.getInputStream(zip.getEntry("test.txt"));
否则,您的选择如下:
  • 使用ZipInputStream扫描一遍zip文件以加载每个条目。如果您有大量资源并且无法重用相同的ZipInputStream,则此过程可能会很慢。
  • 不要将资源打包在嵌套的zip文件中,而是将它们与代码一起内联到jar文件中。
  • 将嵌套的zip文件复制到临时目录,并使用ZipFile类访问它。

2
+1,使用ZipFile类直接获取条目比扫描整个流要更有效率。 - Perception
你能否解释一下你的第一行代码(_如果你能的话..._)? - Adil
当然。如果您的资源zip文件包含在jar文件中,代码示例将无法正常工作。我的意思是,zip文件必须是文件系统上的真实文件,而不是JAR条目。 - Martin Ellis
如何实现呢,我的意思是当我想生成项目的 jar 文件时如何使它成为一个真正的文件?欢迎提供任何资源! - Adil
不知道你的项目将如何部署,很难说。如果在你的类路径上有一个目录,其中包含名为“resources”的子目录,该子目录又包含你的 zip 文件,那么这可能会起作用(你可能需要将 Main.class.getResource("/ resources/...") 更改为 Main.class.getClassLoader().getResource("resources/..."))。如果是我,我可能会将资源与代码打包在同一个 jar 文件中,这样一开始就不会遇到这个问题。 - Martin Ellis

3

你目前的做法肯定行不通。你随意地制定了一个“访问”方案,并在一个完全不知道你在做什么的类中使用它。你可以使用ZipInputStream来读取你要查找的条目:

URL zipFileURL = Thread.currentThread().getContextClassLoader().getResource("zipfile.zip");
InputStream inputStream = zipFileURL.openStream();
ZipInputStream zipInputStream = new ZipInputStream(inputStream);

ZipEntry zipEntry = null;

do {
    zipEntry = zipInputStream.getNextEntry();
    if(zipEntry == null) break;
}
while(zipEntry != null && (! "textfile".equals(zipEntry.getName()));

if(zipEntry != null ) {
    // do some stuff
}

这是临时性的代码,请根据您的需求进行修改。此外,可能有一些更高效的类可以处理Zip文件,例如在Apache Commons IO库中。


0

在zip文件中,test.txt的路径是什么?您需要使用zip文件中的路径来读取此文件。还要确保您的zipfile在类路径中。实际上,您可以将其捆绑在一个jar文件中。


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