本文记录的是如何获取资源文件的路径.

先看看我设置的文件目录结构,如下图所示:

文件目录结构图 ___

Java Build Path的设置如下图所示, 主要看build project之后的文件输出目录:

Java-Build-Path ___

在Java中有两种方式可以获取到文件的路径,通过下面的测试代码看看它们的不同:

1
2
3
4
5
String resPath = this.getClass().getResource("").getPath();
System.out.println("resPath: " + resPath);

String resPath1 = this.getClass().getClassLoader().getResource("").getPath();
System.out.println("resPath1: " + resPath1);

控制台中输出结果如下:

1
2
resPath: /Users/carya/dev/RwProperties/target/classes/edu/cugb/tester/
resPath1: /Users/carya/dev/RwProperties/target/classes/

从结果中可以看到,使用this.getClass().getResource()获得的是代码所在类编译成class文件之后输出文件所在目录位置,而this.getClass().getClassLoader().getResource()获得的是class loader所在路径,该函数查看Java doc解释如下:

Finds the resource with the given name. A resource is some data (images, audio, text, etc) that can be accessed by class code in a way that is independent of the location of the code. The name of a resource is a ‘/’-separated path name that identifies the resource.

This method will first search the parent class loader for the resource; if the parent is null the path of the class loader built-in to the virtual machine is searched. That failing, this method will invoke findResource(String) to find the resource.

使用this.getClass().getResource(String name)函数时,name参数可以使用文件的绝对路径,也可以使用相对路径,如下所示:

1
2
3
4
5
String resPath2 = this.getClass().getResource("../../../jdbc.properties").getPath();
System.out.println("resPath2: " + resPath2);

String resPath3 = this.getClass().getResource("/hbm/setting.txt").getPath();
System.out.println("resPath3: " + resPath3);

上述事例控制台的输出是:

1
2
resPath2: /Users/carya/dev/RwProperties/target/classes/jdbc.properties
resPath3: /Users/carya/dev/RwProperties/target/classes/hbm/setting.txt

而使用this.getClass().getClassLoader().getResource(String name)函数时,name参数则只能使用相对于class loader目录的路径,即相对路径,看下面的事例:

1
2
3
4
5
String resPath4 = this.getClass().getClassLoader().getResource("./hbm/setting.txt").getPath();
System.out.println("resPath4: " + resPath4);

String resPath5 = this.getClass().getClassLoader().getResource("/hbm/setting.txt").getPath();
System.out.println("resPath5: " + resPath5);

控制台输出如下, resPath4使用的是相对路径,能够得到正确结果,而resPath5使用的是绝对路径,抛出Exception:

1
2
3
4
resPath4: /Users/carya/dev/RwProperties/target/classes/hbm/setting.txt
Exception in thread "main" java.lang.NullPointerException
at edu.cugb.tester.PropertiesPath.getFilePath(PropertiesPath.java:39)
at edu.cugb.tester.PropertiesPath.main(PropertiesPath.java:54)

另外,Thread.currentThread().getContextClassLoader().getResource()也可以获取资源文件路径,在获取资源路径方面其使用与this.getClass().getClassLoader().getResource()相似:

1
2
3
4
5
String resPath6 = Thread.currentThread().getContextClassLoader().getResource("").getPath();
System.out.println("resPath6: " + resPath6);

String resPath7 = Thread.currentThread().getContextClassLoader().getResource("./jdbc.properties").getPath();
System.out.println("resPath7: " + resPath7);

控制台的输出如下:

1
2
resPath6: /Users/carya/dev/RwProperties/target/classes/
resPath7: /Users/carya/dev/RwProperties/target/classes/jdbc.properties