java中关于获取程序运行时资源路径的方法,在iteye中搜索到了几个。下面我对这几种写法做个实验。
说明:实验分直接编译运行和用fat jar打成包后运行两部分,因为我相信这个定位资源的问题正是在打包后和在linux服务器上运行时才会遇到的。Eclipse工程名testjar,位于E:\Java\Workspaces\,工程内只有一个类dut.ir.TestJar,资源文件1位于dut/ir/。fat jar选项不选One-Jar。
先来看Class.getResource()方法
public class TestJar { public static void main(String[] args) { System.out.println(TestJar.class.getResource(资源名)); } }
如果资源名填"/",Eclipse里运行时这个方法返回“file:/E:/Java/Workspaces/testjar/bin/”,而在打包后运行时返回null;
如果资源名填"",Eclipse里运行返回“file:/E:/Java/Workspaces/testjar/bin/dut/ir/”,而在打包后运行则返回“jar:file:/E:/Java/Workspaces/testjar/testjar_fat.jar!/dut/ir/”,也就是类所在的完整路径(文件系统路径+包路径);
如果资源名以'/'开头,如"/dut/ir/1",Eclipse运行结果“file:/E:/Java/Workspaces/testjar/bin/dut/ir/1”,打包运行结果则是“jar:file:/E:/Java/Workspaces/testjar/testjar_fat.jar!/dut/ir/1”,也就是说在包结构的根位置寻找,若资源名写“/1”或"/ir/1"是找不到的;
如果资源名不以'/'开头,如"1",Eclipse运行结果“file:/E:/Java/Workspaces/testjar/bin/dut/ir/1”,打包运行结果则是“jar:file:/E:/Java/Workspaces/testjar/testjar_fat.jar!/dut/ir/1”,也就是说在类所在的位置上寻找,若资源名写"dut/ir/1"就意味着定位dut/ir/dut/ir/1,当然找不到;
再实验TestJar.class.getClassLoader().getResource(资源名),ClassLoader.getSystemResource(资源名)和Thread.currentThread().getContextClassLoader().getResource(资源名)方法,它们的结果和TestJar.class.getResource("/" + 资源名)相同。关于原因,这在jdk中Class.getResource方法的说明
那么,如果想在jar包所在的位置定位资源怎么办?再看看这几个方法:
System.out.println(System.getProperty("user.dir")); System.out.println(System.getProperty("java.class.path")); System.out.println(new File("").getAbsolutePath()); System.out.println(TestJar.class.getProtectionDomain().getCodeSource().getLocation().getFile());
输出
E:\Java\Workspaces\testjar E:\Java\Workspaces\testjar\bin E:\Java\Workspaces\testjar /E:/Java/Workspaces/testjar/bin/
如此,可以利用System.getProperty("user.dir")或new File("").getAbsolutePath()这两种写法。
注意:我这里都是直接引用类来实验这些方法,而没有实例化。进来看过的学长如有指正敬请回复,多谢!