欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java 读取jar包中的资源文件夹

程序员文章站 2022-04-28 09:35:13
...

个人博客原文地址:http://www.ltang.me/2016/07/19/Java-jar-read-resource/

最近在做一个工具包的时候,有这么一种需求:在运行main函数时,需要将resources资源文件夹下的xml子文件夹中的文件加载。原本可以使用Main.class.getClassLoader().getResoruceAsStream()将文件一一加载,但是xml子文件夹中的文件非常多,不可能一个个列文件名。所以最初我的写法是:

File parent = new File(ClassLoader.getSystemClassLoader().getResource("").getPath() + "/xml");
File[] files = parent.listFiles();
for (int i = 0; i < xmlFiles.length; i++) {
    File xmlFile = xmlFiles[i];
    //...
}

在IDE中运行并没有问题,能够正常得读取到资源文件夹和文件。但是当我使用maven将工程打成jar包,试图使用命令行启动时,跑到这里就会抛空指针异常了。不断的测试和查资料,终于明白,当打成一个jar包后,整个jar包是一个文件,只能使用流的方式读取资源,这时候就不能通过File来操作资源了,得通过getResourceAsStream来读取文件内容并操作。在IDE中之所以能正常运行,是因为IDE中的资源文件在target/classes目录下,是正常的文件系统结构。

然而问题来了,我不是读一个文件,而是试图读取一个文件夹,依次读取文件夹下所有文件资源。我试图按照网上的说法,读取资源,然后创建一个临时文件,在操作该临时文件,例:

File file = null;
URL res = PostHelper.class.getClassLoader().getResource("xml/");
if (res.toString().startsWith("jar:")) {
    try {
        InputStream input = PostHelper.class.getClassLoader().getResourceAsStream("xml/");
        file = File.createTempFile("tempfile", ".tmp");
        OutputStream out = new FileOutputStream(file);
        int read;
        byte[] bytes = new byte[1024];
        while ((read = input.read(bytes)) != -1) {
            out.write(bytes, 0, read);
        }
        file.deleteOnExit();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
} else {
    file = new File(res.getFile());
}


然而这种方式,也只能操作文件,因为创建出来的是临时文件而非临时文件夹。估计还是有办法解决的,将输入流转为文件夹?这里我也没继续研究了,而是再次搜索解决方案。最终的解决方法如下所示,经过测试,可以完美解决这个问题,顺利读取资源子文件夹中所有文件:

URL url = Main.class.getClassLoader().getResource("xml/");
String jarPath = url.toString().substring(0, url.toString().indexOf("!/") + 2);

URL jarURL = new URL(jarPath);
JarURLConnection jarCon = (JarURLConnection) jarURL.openConnection();
JarFile jarFile = jarCon.getJarFile();
Enumeration<JarEntry> jarEntrys = jarFile.entries();

while (jarEntrys.hasMoreElements()) {
    JarEntry entry = jarEntrys.nextElement();
    String name = entry.getName();
    if (name.startsWith("xml/") && !entry.isDirectory()) {
        doWithInputStream(Main.class.getClassLoader().getResourceAsStream(name));
    }
}
相关标签: java