在jar包中获取另一个jar包中的文件

6

我的设置如下:

  • outer.jar
    • inner.jar
      • file.txt

因此,我正在执行outer.jar,在其中的主类中:

URL url = Main.class.getClassLoader().getResource("file.txt");

URL为:'jar:file:outer.jar!/inner.jar!/file.txt'

但是如果我尝试这样读取它:

url.openStream()

我遇到了一个异常。
Exception in thread "main" java.io.FileNotFoundException: JAR entry inner.jar!/file.txt not found in outer.jar
at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:142)
at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:150)
at java.net.URL.openStream(URL.java:1038)
at Main.main(Main.java:15)

文件肯定在那里。使用JarURLConnection不能实现这个吗?

1
尽量避免JAR嵌套-每个嵌套级别对CPU都非常昂贵,而且没有太多意义。只需将所有类和资源放入一个大的JAR中并正确引用它们-甚至不需要源代码即可工作...只需修改构建系统,使其在打包阶段之前立即附加该字节码。 - specializt
这是由于使用One-JAR将库打包到单个JAR文件中而没有像您建议的那样进行解压缩。他们的网站建议我的代码应该可以工作:http://one-jar.sourceforge.net/index.php?page=details&file=resources - dontocsata
2个回答

2

Jar文件只是另一种名称的简化版Zip文件,所以将它们视为zip文件处理即可:

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;


public class Main{

    public static void main(String[] args) throws IOException {
        URL url = Main.class.getResource("file.jar");
        ZipFile zipFile = new ZipFile(url.getFile());
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while(entries.hasMoreElements()){
            ZipEntry entry = entries.nextElement();
            //InputStream stream = zipFile.getInputStream(entry); <- to handle the file
            //print the names of the files inside the Jar
            System.out.println(entry.getName());
        }
    }

}

注意:这似乎是一个设计问题,因为不建议使用嵌套的JAR文件。

(为什么不将它们合并?)


“Jar”比“Zip”更高级吗? - Hot Licks
是啊,但“Zip”的名字比“Jar”更加有活力。 - Hot Licks
JAR文件远不止是简单的ZIP归档文件。它们具有清单、固定的目录结构、某种程度上固定的压缩(据我所记)、可执行等特点。能够通过ZIP/UNZIP算法读取JAR归档文件的事实...基本上归结于原始JAR开发人员的友好性,就是这样。把JAR文件当作ZIP文件处理的人要么对该主题没有了解,要么只是想听起来聪明,或者必须解决像上面那个问题一样相当奇特的问题。 - specializt
谢谢回答,但不幸的是,我需要一种使用URL的方法,所以你的答案行不通。 - dontocsata
我不能代表原问题提出者,但在我的情况下,我不合并它们的原因是:(1)JAR文件中的类将位于主类路径上,这将与已经存在的同一库的另一个版本发生冲突;(2)如果我重命名包,在使用IDE时,重命名的包会自动完成,当尝试完成主库中的包时,使生活变得不那么美好。 - Hakanai

1

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