读取jar文件内容

一、SpringBoot项目打包成jar后读取文件的大坑,使用ClassPathResource获取classpath下文件失败

java.io.FileNotFoundException: class path resource [WorldPayTemplate.txt] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/opt/app.jar!/BOOT-INF/classes!/WorldPayTemplate.txt

读取文件模本使用的是

        ClassPathResource resource = new ClassPathResource("WorldPayTemplate.txt");
        log.info("读取文件对象,{}",resource);
        StringBuilder builder = new StringBuilder();
        try {
            File file = resource.getFile();
            log.info("file对象,{}",file);
            BufferedReader reader = new BufferedReader(new FileReader(file));
            log.info("BufferedReader对象,{}",reader);
            String line = null;
            while ((line = reader.readLine()) != null) {
                log.info("单行文件内容:{}",line);
                builder.append(line);
            }
            log.info("文件内容:{}",builder);
        } catch (IOException e) {
            log.error("文件读取异常:{}",e);
            throw new MallException(ErrorMessage.FILE_READ_ERROR.getErrorCode());
        }

抛到测试环境出现文件找不到错误,本地测试没问题

二、解决方法

使用ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

String txt = "";
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("templates/layout/email.html");
Resource resource = resources[0];
//获得文件流,因为在jar文件中,不能直接通过文件资源路径拿到文件,但是可以在jar包中拿到文件流
InputStream stream = resource.getInputStream();
StringBuilder buffer = new StringBuilder();
byte[] bytes = new byte[1024];
try {
    for (int n; (n = stream.read(bytes)) != -1; ) {
        buffer.append(new String(bytes, 0, n));
    }
} catch (IOException e) {
    e.printStackTrace();
}
txt = buffer.toString();

三、出现这个问题的原因

其实这是一个jar包发布的大坑,使用getFile()的时候的坑,对 ClassPathResource resource = new ClassPathResource("WorldPayTemplate.txt");以及File file = resource.getFile();进行debug,结果返回的是一个Jar协议地址:jar:file:/xxx/xx.jar!/xxxx。

 然后继续跟踪到getFile(java.net.URL, java.lang.String)中,有如下的判断:

public static File getFile(URL resourceUrl, String description) throws FileNotFoundException {
    Assert.notNull(resourceUrl, "Resource URL must not be null");
    if (!"file".equals(resourceUrl.getProtocol())) {
        throw new FileNotFoundException(description + " cannot be resolved to absolute file path because it does not reside in the file system: " + resourceUrl);
    } else {
        try {
            return new File(toURI(resourceUrl).getSchemeSpecificPart());
        } catch (URISyntaxException var3) {
            return new File(resourceUrl.getFile());
        }
    }
}

 

因为resourceUrl.getProtocol()不是file,而是 jar,这样就抛出了一个FileNotFoundException异常。

ResouceUtils.getFile()是专门用来加载非压缩和Jar包文件类型的资源,所以它根本不会去尝试加载Jar中的文件,要想加载Jar中的文件,只要用可以读取jar中文件的方式加载即可,比如 xx.class.getClassLoader().getResouceAsStream()这种以流的形式读取文件的方式,所以使用读取文件流就可以拿到了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值