问题描述
在 Maven 项目中,从 resource 资源目录用文件输入流读入时,编译时运行正常,但打成jar包后运行jar包报错:
Exception in thread “main” java.lang.RuntimeException:
java.io.FileNotFoundException
原因分析
先上初始代码:
String name = args[0];
name = name.replace("#","_");
String path = "pianoKey/" + name + ".mp3";
InputStream is = new FileInputStream("src/main/resources/" + path);我们在获取文件输入流的时候大部分都会选择使用相对路径来读入一个文件(一般不使用绝对路径,可移植性太差)
这个时候,正常去在项目下编译运行时没有任何问题的,但我们把这个项目打包成可执行jar包的时候,在终端运行这个jar包,就会报错,系统找不到指定的这个文件路径。

原因就在于此时打包后的jar包默认是在target文件夹下,而我们的代码默认的工作目录是项目的目录,所以一旦在jar包所在目录运行这个jar包,相对路径就不对了,就会报路径错误。
解决方案
方法一
通过获取已有类的一个class对象的类加载器,然后用里面的 getResourceAsStream()方法 。
注:已有类就是项目文件夹下的任何一个类,比如我在src/main/java下写了一个叫做Main的类
简单解释一下这个方法的原理:
- 调用DBUtil.class.getClassLoader()就会获取到编译后的classes目录
- 所谓的类加载器就是告诉JVM从哪个文件夹去执行class文件
- getResourceAsStream()就是获取指定文件的输入流
String name = args[0];
name = name.replace("#","_");
String path = "pianoKey/" + name + ".mp3";
InputStream is = Main.class.getClassLoader().getResourceAsStream(path);方法二
通过已有的工具类来获取,比如比较有名的开源工具类 hutool 中的ResourceUtil类:
String name = args[0];
name = name.replace("#","_");
String path = "pianoKey/" + name + ".mp3";
InputStream is = ResourceUtil.getStream(path);
苏ICP备16040035号-5