您好,欢迎访问一九零五行业门户网

如何在Java中读取JAR包中的资源文件?

1、需求       在java项目中,需要读取resource资源目录下的文件,以及遍历指定资源目录下的所有文件,并且在读取文件时保留文件相对路径。
2、问题       在idea中运行时,可以获取并遍历指定资源,但是将java项目打成jar包运行后,就无法获取resource资源目录下的文件。
3、idea读取resource资源       编译后,资源文件放在target目录下,每一个资源文件实实在在存在于磁盘中。
3.1、方法1       直接通过绝对路径读取,如果file是目录,也可以通过listfiles递归遍历目录下文件:
string absolutepath = "资源文件绝对路径";file file = new file(absolutepath);if (file.isdirectory()) { file[] children = file.listfiles();}
3.2、方法2 通过相对路径读取:
string path = "template"; //相对resource路径file file = resourceutils.getfile(resourceutils.classpath_url_prefix + path);if (file.isdirectory()) { file[] children = file.listfiles();}
4、打成jar包后读取resource资源 以上两种方法无法读取jar包中的资源文件。
打成jar包后,jar包是一个单独的文件而不是文件夹,所以通过文件路径是无法定位到资源文件的。此时,可通过类加载器读取jar包中的资源文件。
4.1、读取jar包中的资源文件 这种方式只能读取jar包中单个文件,因为读取出来的是inputstream流,无法保留文件相对于resource的路径,所以无法对jar包中资源进行遍历。
string path = "/resource相对路径";inputstream is = this.class.getresourceasstream(path);byte[] buff = new byte[1024];string filepath = "保存文件路径";string filename = "保存文件名";file file = new file(filepath + filename);fileutils.copyinputstreamtofile(is, file);
4.2、遍历jar包资源目录以复制resource资源目录为例,分别对本地和jar包中的资源进行复制。
如下所示:
我要复制resource资源目录下的template文件夹下的所有内容;
然后保存到c:/users/asus/desktop/savepath文件夹下。
4.2.1、环境判断
public static void main(string[] args) throws urisyntaxexception { // test为当前类名 uri uri = test.class.getprotectiondomain().getcodesource().getlocation().touri(); // temppath: 文件保存路径 string temppath = "c:/users/asus/desktop/savepath"; string sourcedir = "template"; //资源文件夹 if (uri.tostring().startswith("file")) { // idea运行时,进行资源复制 copylocalresourcesfiletotemp(sourcedir + "/", "*", temppath + "/" + sourcedir); } else { // 获取jar包所在路径 string jarpath = uri.tostring(); uri = uri.create(jarpath.substring(jarpath.indexof("file:"),jarpath.indexof(".jar") + 4)); // 打成jar包后,进行资源复制 test.copyjarresourcesfiletotemp(uri, temppath, "boot-inf/classes/" + sourcedir); }}
4.2.2、复制本地项目的资源文件
/** * 复制本地资源文件到指定目录 * @param fileroot 需要复制的资源目录文件夹 * @param regexpstr 资源文件匹配正则,*表示匹配所有 * @param tempparent 保存地址 */ public static void copylocalresourcesfiletotemp(string fileroot, string regexpstr, string tempparent) { try { resourcepatternresolver resolver = new pathmatchingresourcepatternresolver(); resource[] resources = resolver.getresources(fileroot + regexpstr); for (resource resource : resources) { file newfile = new file(tempparent, resource.getfilename()); if (newfile.exists()) { newfile.delete(); } inputstream stream = null; try { stream = resource.getinputstream(); } catch (exception e) { // 如果resource为文件夹时,会报异常,这里直接忽略这个异常 } if (stream == null) { newfile.mkdirs(); copylocalresourcesfiletotemp(fileroot + resource.getfilename() + "/", regexpstr, tempparent + "/" + resource.getfilename()); } else { if (!newfile.getparentfile().exists()) { newfile.getparentfile().mkdirs(); } org.apache.commons.io.fileutils.copyinputstreamtofile(stream, newfile); } } } catch (exception e) { log.error("failed to copy local source template", e); } }
4.2.3、复制jar包里的资源文件
/** * 复制jar包中的资源文件到指定目录 * @param path jar包所在路径 * @param temppath 保存目录 * @param fileprefix 需要进行复制的资源文件目录:以boot-inf/classes/开头 */ public static void copyjarresourcesfiletotemp(uri path, string temppath, string fileprefix) { try { list<map.entry<zipentry, inputstream>> collect = readjarfile(new jarfile(path.getpath()), fileprefix).collect(collectors.tolist()); for (map.entry<zipentry, inputstream> entry : collect) { // 文件相对路径 string key = entry.getkey().getname(); // 文件流 inputstream stream = entry.getvalue(); file newfile = new file(temppath + key.replaceall("boot-inf/classes", "")); if (!newfile.getparentfile().exists()) { newfile.getparentfile().mkdirs(); } org.apache.commons.io.fileutils.copyinputstreamtofile(stream, newfile); } } catch (ioexception e) { log.error("failed to copy jar source template", e); } }
@sneakythrows public static stream<map.entry<zipentry, inputstream>> readjarfile(jarfile jarfile, string prefix) { stream<map.entry<zipentry, inputstream>> readingstream = jarfile.stream().filter(entry -> !entry.isdirectory() && entry.getname().startswith(prefix)) .map(entry -> { try { return new abstractmap.simpleentry<>(entry, jarfile.getinputstream(entry)); } catch (ioexception e) { return new abstractmap.simpleentry<>(entry, null); } }); return readingstream.onclose(() -> { try { jarfile.close(); } catch (ioexception e) { log.error("failed to close jarfile", e); } }); }
以上就是如何在java中读取jar包中的资源文件?的详细内容。
其它类似信息

推荐信息