前言
博主个人社区:开发与算法学习社区 博主个人主页:Killing Vibe的博客 欢迎大家加入,一起交流学习~~
问题描述
Maven项目下,从resouces目录下把文件读入内存时,例如将sql文件用文件输入流读入时,编译时运行正常,但打成jar包后运行jar包报错:
Exception in thread “main” java.lang.RuntimeException:
java.io.FileNotFoundException
原因分析:
先上初始代码:
代码语言:javascript复制 InputStream in = new FileInputStream("src/main/resources/init.sql");
我们在获取文件输入流的时候大部分都会选择使用相对路径来读入一个文件(一般不使用绝对路径,可移植性太差)
这个时候,正常去在项目下编译运行时没有任何问题的,但我们把这个项目打包成可执行jar包的时候,在终端运行这个jar包,就会报错,系统找不到指定的这个文件路径:
原因就在于此时打包后的jar包
默认是在target
文件夹下,而我们的代码默认的工作目录
是项目的目录
,所以一旦在jar包所在目录运行这个jar包,相对路径就不对了,就会报路径错误。
–
解决方案:
1.把这个jar包移动到工作目录上运行(很笨的方法)
2.下面推荐一种做法就是使用类加载器的方式引入资源文件
先上代码:
代码语言:javascript复制 InputStream in = DBUtil.class.getClassLoader().
getResourceAsStream("init.sql");
直接获取已有类的一个class对象的类加载器,然后用里面的 getResourceAsStream()
方法 。
注:已有类就是项目文件夹下的任何一个类,比如我在src/main/java下写了一个叫做DBUtil的类
因为项目中的源文件打包编译之后都会放在 target
文件夹下的 classes
文件夹中(包括资源文件),而刚好这个jar包
也是默认放在target
文件夹下,所以两者工作目录相同,就不会报错
简单解释一下这个方法的原理:
- 调用DBUtil.class.getClassLoader()就会获取到编译后的classes目录
- 所谓的类加载器就是告诉JVM从哪个文件夹去执行class文件
- getResourceAsStream()就是获取指定文件的输入流
总结
好处:这就是处理相对路径的通用写法!!
充分体现了Java的可移植性,无论哪个操作系统,哪个电脑,这样写一写百通~~~