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

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

最新文章

  1. Werewolf流程分析
  2. 【python】调用机器喇叭发出蜂鸣声(Beep)
  3. java 线程的终止与线程中断
  4. ARP 命令运行实现静态IP/MAC绑定
  5. HTML+CSS学习笔记(5)- 与浏览者交互,表单标签
  6. JavaScript高级程序设计(第三版)学习笔记13、14章
  7. InvoiceCancelSendApAction
  8. null和undefined的区别
  9. C#中利用JQuery实现视频网站
  10. 输入一个数字n 如果n为偶数则除以2,若为奇数则加1或者减1,直到n为1,求最少次数 写出一个函数
  11. python摸爬滚打之day33----线程
  12. [c/c++] programming之路(30)、位运算(一)
  13. diango admin 添加成员报错
  14. c/c++ include 头文件的方式
  15. 环境配置 jupyter代码自动补全
  16. Agile PLM 开发中AgileAPI类型对应控制台分类说明
  17. Angular 学习笔记 ( timezone + moment + material date-picker + date pipe + asp.net core )
  18. R中的高效批量处理函数(lapply sapply apply tapply mapply)(转)
  19. Java - "JUC" ReentrantLock释放锁
  20. 在Ubuntu虚拟机上安装DVWA

热门文章

  1. ASP.NET CORE系列【六】Entity Framework Core 之数据迁移
  2. WPF 为资源字典 添加事件响应的后台类
  3. SQL Server 2016新特性:DROP IF EXISTS
  4. Android零基础入门第89节:Fragment回退栈及弹出方法
  5. 无法解决 equal to 操作中 "SQL_Latin1_General_CP1_CI_AS" 和 "Chinese_PRC_CI_AS" 之间的排序规则冲突。
  6. Delphi xe5 StyleBook的用法(待续)
  7. 还在羡慕BAT等公司的大流量的架构吗,commonrpc 是一个以netty 传输协议框架为基础(支持FTP)
  8. c# 可移动可改变大小的控件
  9. 用Golang让自己的电脑自动登录“上网管理”系统
  10. Laravel中我们登录服务器通过 Tinker 手动创建后台管理用户