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. 如何快速生成数据文件(fsutil命令,使用CreateFile和SetEndOfFile API函数,fopen和fseek RTL函数)

    1. fsutil 命令 文件会瞬间生成,因为实际上Windows只是分配了名称.地址和空间给该文件,并没有读写任何文件内容 100M=1024x1024x100 fsutil file create ...

  2. liunx 桥接 上网 ip配置 外部网络访问

    一.设置VMware 在vmware的[编辑]-->[虚拟网络编辑器]设置:将VMnet0设置为“桥接”,并桥接到宿主机器的网卡(可以是有线或者无线网络).   二.设置虚拟机系统(以cento ...

  3. Linux学习之“vfork函数”

    为什么使用vfork()? 希望父子进程执行不同的代码.例如: 网络服务程序中,父进程等待客户端的服务请求,当请求达到时,父进程调用fork,使子进程处理该次请求,而父进程继续等待下一个服务请求到达. ...

  4. 【Repo】推送一个已有的代码到新的 gerrit 服务器

    1.指定项目代码库中迭代列出全部ProductList(.git)到pro.log文件中 repo forall -c 'echo $REPO_PROJECT' | tee pro.log 命令解读: ...

  5. 零元学Expression Blend 4 - Chapter 8 用实例了解布局容器系列-「Grid」

    原文:零元学Expression Blend 4 - Chapter 8 用实例了解布局容器系列-「Grid」 本系列将教大家以实做案例认识Blend 4 的布局容器,此章介绍的是Blend 4 里的 ...

  6. UWP开发学习笔记3

    获取可视化状态列表 private void Button_Click(object sender, RoutedEventArgs e) { //获取CheckBox控件可视化树中的子元素数量 in ...

  7. MIPS开发板的“不二”选择——Creator Ci20单板计算机评测(芯片是君正JZ4780 ,也就是MIPS R3000,系统推荐Debian或深度,官网就有,其它语言有FreePascal和Go和Java和Python)

    在MIPS架构的CPU上开发软件,当然需要使用MIPS专用的工具链来编译代码.不过一般的LINUX发行版内都有相应的配套工具链供用户使用.Ci20出厂时的LINUX发行版为DEBIAN 7.5,相应的 ...

  8. DELPHI XE2 采用 JSON 的方式来序列化对象

    DELPHI XE2 采用 JSON 的方式来序列化对象 以下代码测试通过.问题是里面的中文,在反序列化后是乱码. 1. 序列化对象为字符串,Subject 里面的中文看起来正常,仍然是中文: 2.  ...

  9. msys2 安装笔记(可以按照这个关键字搜索)

    以前一直在用 msys,最近发现还有个 msys2,并且msys2 配套的编译器是MinGW-w64. 就试着用了用,感觉还不错,这里把安装过程记录一下. 简单的说,MSYS2 是MSYS的一个升级版 ...

  10. Angular4初学

    [1].在学习Angular4之前,首先要了解一些typescript的知识. 以下是我的总结:https://gitee.com/FangXiaoQi123/angularJSCeShi/blob/ ...