编译运行时的资源读取路径
类名.class与getClass()
类名.class与getClass()实际上是一个东西,只不过getClass()获取到的是当前代码下的Class,而类名.class则自由,可以随意指定哪个类文件。
假如有A.class,然后在A中执行getClass(),那此刻可以完全视它们是一个意思。
需要注意的,如果用类名.class形式,那就需要时刻注意查询文件的路径是依据类名.class的位置来了。
getResource()与getClassLoader().getResource()
//表示只会在当前调用类所在的同一路径下查找该fileName文件,表示相对路径:
getClass().getResource(fileName)
//如果在fileName前加了"/",表示绝对路径,取classpath根目录/下的该文件:
getClass().getResource("/" + fileName)
//表示只会在根目录下(/)查找该文件:
getClass().getClassLoader().getResource(fileName):
相当于:
getClass().getResource("/" + fileName)
getClass().getResource()具体用法
如上面的Maven工程目录,StartApp类位于go包下面,我们使用getClass().getResource("start.fxml")时,在resource资源目录下的go目录需要有对应的start.fxml,否则会报错:Location is not set。
补充:不能直接在java包下的go目录存放start.fxml,同样会报错,因为maven项目在java包目录只会扫描java文件,不会扫描资源文件。至于为什么在resource目录下就可以读到,我们编译运行时可以观察target目录,它们最终会合并到一块:
System.out.println(StartApp.class.getResource("/view/RootLayout.fxml"));
System.out.println(StartApp.class.getClassLoader().getResource("/view/RootLayout.fxml"));
//结果如下:
file:/C:/Users/Heawill/Desktop/BroadcastSystemNew/target/classes/view/RootLayout.fxml
null
//区别:
class.getResource("/") == class.getClassLoader().getResource("")
//其实,Class.getResource和ClassLoader.getResource本质上是一样的,都是使用ClassLoader.getResource加载资源的。
//Class.getResource真正调用ClassLoader.getResource方法之前,会先获取文件的路径(path不以'/'开头时,默认是从此类所在的包下取资源;path以'/'开头时,则是从项目的ClassPath根下获取资源)。
实际代码样例
第一种:
URL url = 类名.class.getClassLoader().getResource("conf.properties");
URL url = getClass().getClassLoader().getResource("conf.properties");
第二种:
URL url = 类名.class.getClass().getResource("/view/RootLayout.fxml");
URL url = getClass().getResource("/view/RootLayout.fxml");
//第二种通过URL我们可以获取路径信息:
//toString() : file:/C:/Users/Heawill/Desktop/BroadcastSystemNew/target/classes/view/RootLayout.fxml
String string = url.toString();
//getPath() : /C:/Users/Heawill/Desktop/BroadcastSystemNew/target/classes/view/RootLayout.fxml
String path = url.getPath();
//url.getFile() : /C:/Users/Heawill/Desktop/BroadcastSystemNew/target/classes/view/RootLayout.fxml
File file = new File(url.getFile());
//file.getAbsolutePath() :C:\Users\Heawill\Desktop\BroadcastSystemNew\target\classes\view\RootLayout.fxml
String url = file.getAbsolutePath();
Jar包时的资源读取
编译运行时由于存在真实的文件和路径,所以对资源的读写都可以正常进行,但是当打包成jar包,写的话由于jar文件就不支持了。
//无论时编译运行时还是Jar文件时,getClass().getResource("/view/start.fxml")都能读取到对应的文件,只不过通过打印,我们发现路径发生了改变:
//编译运行时:
file:/G:/DevelopProject/BroadcastSystem/target/classes/view/start.fxml
//Jar文件时:
jar:file:/G:/DevelopProject/BroadcastSystem/target/jfx/app/BroadcastSystemNew-1.2-SNAPSHOT.jar!/view/start.fxml
补充
其他方法:
//以下方法返回的是InputStream类型,路径跟非AsStream的方法一样
getClass().getClassLoader().getResourceAsStream(file)
getClass().getResourceAsStream(file)
Maven项目中的/
Maven项目中的/代表的是的ClassPath根路径,即java或resource目录
注意
有时候fxml等其他资源都是直接在IDEA中复制或者剪切,这可能会导致路径虽然没问题,但是也会报错:Location is not set,这直接通过重构工程解决:
参考
https://blog.csdn.net/suchahaerkang/article/details/100927545