Java 读取jar包中的资源文件夹
记录将项目打成一个可执行jar包后,如何读取jar包中的资源文件夹。
最近在做一个工具包的时候,有这么一种需求:在运行main函数时,需要将resources资源文件夹下的xml子文件夹中的文件加载。原本可以使用Main.class.getClassLoader().getResoruceAsStream()将文件一一加载,但是xml子文件夹中的文件非常多,不可能一个个列文件名。所以最初我的写法是:
1 2 3 4 5 6
| 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目录下,是正常的文件系统结构。
然而问题来了,我不是读一个文件,而是试图读取一个文件夹,依次读取文件夹下所有文件资源。我试图按照网上的说法,读取资源,然后创建一个临时文件,在操作该临时文件,例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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()); }
|
然而这种方式,也只能操作文件,因为创建出来的是临时文件而非临时文件夹。估计还是有办法解决的,将输入流转为文件夹?这里我也没继续研究了,而是再次搜索解决方案。最终的解决方法如下所示,经过测试,可以完美解决这个问题,顺利读取资源子文件夹中所有文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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)); } }
|