SpringBoot项目构建成jar运行后,如何正确读取resource下的文件

不管你使用的是SpringBoot 1.x还是SpringBoot2.x,在开Dev环境中使用eclipse、IEAD、STS等IDE工具,进行resource目录下文件的获取,简单的采用@Value注解的形式就可以得到,文件读取的主知一般情况下也是没有问题的,比如

File file = ResourceUtils.getFile("classpath:exceltmp/template_export.xls");

度娘检索出来的文章也基本上告诉你,这样是没有问题的。But,使用mvn package构建成jar文件,运行后报异常如下:

java.io.FileNotFoundException: class path resource [exceltmp/template_export.xls] cannot be resolved to absolute file path because it does not reside in the file system:jar:file:/Users/apple/project-code/xdod-project/xdod-backend/target/xdod-backend.jar!/BOOT-INF/classes!/exceltmp/template_export.xls

Resource下的文件是存在于jar这个文件里面,在磁盘上是没有真实路径存在的,它其实是位于jar内部的一个路径。所以通过ResourceUtils.getFile或者this.getClass().getResource("")方法无法正确获取文件。

有一种比较偷懒的做法:将文档放在项目外,应用可以读取到的一个固定目录。按正常的方式读取即可,但可维护性比较差,很容易被误操作丢失。

文本文件读取

这种情况下可以采用流的方式来读取文件,拿到文件流再进行相关的操作。如果你使用Spring框架的话,可以采用ClassPathResource来读取文件流,将文件读取成字符串才进行二次操作,比较适用于文本文件,如properties,txt,csv,SQL,json等,代码参考:

String data = "";
ClassPathResource cpr = new ClassPathResource("static/file.txt");
try {
byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream());
data = new String(bdata, StandardCharsets.UTF_8);
} catch (IOException e) {
LOG.warn("IOException", e);
}

这里提供一个工具类来帮助大家读取文件:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.stream.Collectors; import org.springframework.core.io.ClassPathResource; public final class ClassPathResourceReader {
/**
* path:文件路径
* @since JDK 1.8
*/
private final String path; /**
* content:文件内容
* @since JDK 1.6
*/
private String content; public ClassPathResourceReader(String path) {
this.path = path;
} public String getContent() {
if (content == null) {
try {
ClassPathResource resource = new ClassPathResource(path);
BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
content = reader.lines().collect(Collectors.joining("\n"));
reader.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
return content;
}
}

使用方式也是相当简单

String content = new ClassPathResourceReader("log4j.properties").getContent();

非文本文件读取

更多的情况是读取非文本文件,比如xls,还是希望拿到一个文件,再去解析使用。参考代码如下:

ClassPathResource classPathResource = new ClassPathResource("exceltmp/template_export.xls"");

InputStream inputStream = classPathResource.getInputStream();
//生成目标文件
File somethingFile = File.createTempFile("template_export_copy", ".xls");
try {
FileUtils.copyInputStreamToFile(inputStream, somethingFile);
} finally {
IOUtils.closeQuietly(inputStream);
}

拿到目标文件后,再按照正常的取法如ResourceUtils.getFile,读取即可。

参考文章:https://stackoverflow.com/questions/25869428/classpath-resource-not-found-when-running-as-jar

获取更多内容请关注公众号

SpringBoot项目构建成jar运行后,如何正确读取resource下的文件的更多相关文章

  1. maven将自己的springboot项目打包成jar包后,作为工具包引入其他项目,找不到jar中的类

    将springboot项目打包成jar包,作为工具包导入项目后,找不到jar中的类. 原因是:springboot项目使用了自动的打包插件. 原先的插件配置: <build> <pl ...

  2. Springboot项目打包成jar运行2种方式

    最近公司有个项目需要移植到SpringBoot框架上,项目里面又有许多第三方jar包,在linux服务器上最方便的就是用jar的方式来运行SpringBoot项目了,因此我研究了2种打jar包的方式, ...

  3. Spring项目读取resource下的文件

    目录 一.前提条件 二.使用ClassPathResource类读取 2.1.Controller.service中使用ClassPathResource 2.2.单元测试使用ClassPathRes ...

  4. springboot读取resource下的文件

    public static String DEFAULT_CFGFILE = ConfigManager.class.getClassLoader().getResource("conf/s ...

  5. springboot 读取 resource 下的文件

    ClassPathResource classPathResource = new ClassPathResource("template/demo/200000168-check-resp ...

  6. SpringBoot项目打包成jar后,启动脚本

    将springboot项目打包成jar后,上传至服务器,每次都需要手敲命令,重新部署项目,可将这些命令写入脚本中,直接运行. 启动脚本(start.sh): CUR_PATH=$(cd "$ ...

  7. SpringBoot 项目打包后获取不到resource下资源的解决

    SpringBoot 项目打包后获取不到resource下资源的解决 在项目中有几个文件需要下载,然后不想暴露真实路径,又没有CDN,便决定使用接口的方式来获取文件.最初的时候使用了传统的方法来获取文 ...

  8. 用gradle把springboot项目打包成jar

    ``` 用gradle把springboot项目打包成jar ```### build.gradle 中添加 buildscript { repositories { mavenLocal() mav ...

  9. SpringBoot读取Resource下文件的几种方式(十五)

    需求:提供接口下载resources目录下的模板文件,(或者读取resources下的文件)给后续批量导入数据提供模板文件. 方式一:ClassPathResource //获取模板文件:注意此处需要 ...

随机推荐

  1. delphi文件操作(比较全)

    Delphi中默认有input和output两个文件变量,使用可以不用定义,直接使用. 但: input:只读.output:只写.用时注意以免引起异常. 文件是由文件名标识的一组数据的集合,文件通常 ...

  2. Win8Metro(C#)数字图像处理--2.33图像非线性变换

    原文:Win8Metro(C#)数字图像处理--2.33图像非线性变换  [函数名称] 图像非线性变换函数NonlinearTransformProcess(WriteableBitmap src ...

  3. js通过沿着作用域链还是原型链查找变量

    这是一道非常典型的JS闭包问题,结果和具体的解析请看这里. 对于其中的`函数作用域链的问题`博主似乎没有解释清楚,有一些疑问:js中的变量到底是沿着作用域链还是原型链查找呢? 首先,要分清作用域链与原 ...

  4. RocketMQ配置

    安装&配置 1.Clone&Build git clone -b develop https://github.com/apache/incubator-rocketmq.git cd ...

  5. 《SpringMVC从入门到放肆》十五、SpringMVC之上传文件

    上一篇我们学习了数据分组校验,已经可以灵活的在项目中进行数据校验了,今天来学习SpringMVC的上传文件功能.相对来说SpringMVC的上传功能,还是比较简单的. 一.添加依赖 <depen ...

  6. react中使用高德地图的原生API

    干货,无话 1.react-create-app,创建新react项目 2.npm install react-amap,引入高德地图的封装 3.编写组件index.js import React f ...

  7. JVM检测&工具

    前几篇篇文章介绍了介绍了JVM的参数设置并给出了一些生产环境的JVM参数配置参考方案.正如之前文章中提到的JVM参数的设置需要根据应用的特性来进行设置,每个参数的设置都需要对JVM进行长时间的监测,并 ...

  8. 写在Logg SAP项目上线之际

    根据大环境大行业的惯用做法,公司建立Logg品牌是在意料之中.毫无意外的,Logg也要上到SAP系统中. 其实按它的业务模式来说上SAP系统并不困难,早在几年前就已经有做过了.无非就是接单不生产,外包 ...

  9. Scala 学习之路(四)—— 数组Array

    一.定长数组 在Scala中,如果你需要一个长度不变的数组,可以使用Array.但需要注意以下两点: 在Scala中使用(index)而不是[index]来访问数组中的元素,因为访问元素,对于Scal ...

  10. 如何为linux服务器配置DNS解析?

    本文建立在已经搭建好DNS服务器时,为linux机器配置DNS服务器的三种方式. IP地址是网络上标识站点的数字地址,为了方便记忆,采用域名来代替IP地址标识站点地址.DNS(域名解析)就是域名到IP ...