SpringBoot项目构建成jar运行后,如何正确读取resource下的文件
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
获取更多内容请关注公众号
最新文章
- Werewolf流程分析
- 【python】调用机器喇叭发出蜂鸣声(Beep)
- java 线程的终止与线程中断
- ARP 命令运行实现静态IP/MAC绑定
- HTML+CSS学习笔记(5)- 与浏览者交互,表单标签
- JavaScript高级程序设计(第三版)学习笔记13、14章
- InvoiceCancelSendApAction
- null和undefined的区别
- C#中利用JQuery实现视频网站
- 输入一个数字n 如果n为偶数则除以2,若为奇数则加1或者减1,直到n为1,求最少次数 写出一个函数
- python摸爬滚打之day33----线程
- [c/c++] programming之路(30)、位运算(一)
- diango admin 添加成员报错
- c/c++ include 头文件的方式
- 环境配置 jupyter代码自动补全
- Agile PLM 开发中AgileAPI类型对应控制台分类说明
- Angular 学习笔记 ( timezone + moment + material date-picker + date pipe + asp.net core )
- R中的高效批量处理函数(lapply sapply apply tapply mapply)(转)
- Java - ";JUC"; ReentrantLock释放锁
- 在Ubuntu虚拟机上安装DVWA
热门文章
- ASP.NET CORE系列【六】Entity Framework Core 之数据迁移
- WPF 为资源字典 添加事件响应的后台类
- SQL Server 2016新特性:DROP IF EXISTS
- Android零基础入门第89节:Fragment回退栈及弹出方法
- 无法解决 equal to 操作中 ";SQL_Latin1_General_CP1_CI_AS"; 和 ";Chinese_PRC_CI_AS"; 之间的排序规则冲突。
- Delphi xe5 StyleBook的用法(待续)
- 还在羡慕BAT等公司的大流量的架构吗,commonrpc 是一个以netty 传输协议框架为基础(支持FTP)
- c# 可移动可改变大小的控件
- 用Golang让自己的电脑自动登录“上网管理”系统
- Laravel中我们登录服务器通过 Tinker 手动创建后台管理用户