问题描述

今天分享一个发版遇到问题,读取resource下文件时报错,但是本地环境启动时并不会报错,打包到线上jar包运行报错,最终定位到代码:

File file = ResourceUtils.getFile("classpath:data20220111.txt");
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(file), "GBK");

报错如下

java.io.FileNotFoundException: class path resource [data20220111.txt] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/Users/wangjiesheng/IdeaProjects/erp-gateway/target/erp-gateway.jar!/BOOT-INF/classes!/data20220111.txt
	at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:217)
	at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:180)
	at com.fastjz.util.InitIPBeanUtil.getIpBeans(InitIPBeanUtil.java:29)
	at com.fastjz.config.CommandLineRunnerImpl.run(CommandLineRunnerImpl.java:43)
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:792)
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:776)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:319)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1247)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1236)
	at com.fastjz.Application.main(Application.java:12)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:109)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)

解决方法

这是其中一种,本地运行正常,打成jar包也正常,推荐用此方式

ClassPathResource classPathResource = new ClassPathResource("data20220111.txt");
InputStreamReader inputStreamReader = new InputStreamReader(classPathResource.getInputStream(), "GBK");

事故原因

推测主要原因是springboot内置tomcat,打包后是一个jar包,无法直接读取jar包中的文件,读取只能通过类加载器读取

更多解决方法

方式一:
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("data20220111.txt");

方式二:
InputStream inputStream = this.getClass().getResourceAsStream("data20220111.txt");