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包中的资源文件?的详细内容。
   
 
   