一、Java项目中创建文件对象
下面是一个java项目,名称为ResourceTest。在这个项目中有4个文件,1.properties、2.properties、3.properties、4.properties。
编译完成后,这4个文件的路径如下:
…ResourceTest/1.properties
…ResourceTest/bin/2.properties
…ResourceTest/bin/com/ghs/test/3.properties
…ResourceTest/bin/com/ghs/test/sub/4.properties
所以,我们可以通过下面的代码来为这4个文件创建File对象,其中,”.”或者”./”表示当前目录,也就是JVM的启动目录。
public class MainTest {
public static void main(String[] args) {
File file1 = new File("./1.properties");
//File file1 = new File("test1.txt");
File file2 = new File("./bin/2.properties");
//File file2 = new File("bin/2.properties");
File file3 = new File("./bin/com/ghs/test/3.properties");
//File file3 = new File("bin/com/ghs/test/3.properties");
File file4 = new File("./bin/com/ghs/test/sub/4.properties");
//File file4 = new File("bin/com/ghs/test/sub/4.properties");
try {
System.out.println(file1.exists()+":"+file1.getCanonicalPath());
System.out.println(file2.exists()+":"+file2.getCanonicalPath());
System.out.println(file3.exists()+":"+file3.getCanonicalPath());
System.out.println(file4.exists()+":"+file4.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果如下:
true:D:\me\open\open-project\ResourceTest\1.properties
true:D:\me\open\open-project\ResourceTest\bin\2.properties
true:D:\me\open\open-project\ResourceTest\bin\com\ghs\test\3.properties
true:D:\me\open\open-project\ResourceTest\bin\com\ghs\test\sub\4.properties
二、WEB项目中创建文件对象
下面的是一个Java Web项目,名称为ResourceWeb。这个项目下同样有4个文件:1.properties、2.properties、3.properties、4.properties。
编译完成后,这4个文件的路径如下:
…/ResourceWeb/1.properties
…/ResourceWeb/build/classes/2.properties
…/ResourceWeb/build/classes/com/ghs/test/3.properties
…/ResourceWeb/build/classes/com/ghs/test/sub/4.properties
所以,我们可以通过下面的代码来创建web项目的文件对象。
public class MainTest {
public static void main(String[] args) {
File file1 = new File("./1.properties");
//File file1 = new File("test1.txt");
File file2 = new File("./build/classes/2.properties");
//File file2 = new File("build/classes/2.properties");
File file3 = new File("./build/classes/com/ghs/test/3.properties");
//File file3 = new File("build/classes/com/ghs/test/3.properties");
File file4 = new File("./build/classes/com/ghs/test/sub/4.properties");
//File file4 = new File("build/classes/com/ghs/test/sub/4.properties");
try {
System.out.println(file1.exists()+":"+file1.getCanonicalPath());
System.out.println(file2.exists()+":"+file2.getCanonicalPath());
System.out.println(file3.exists()+":"+file3.getCanonicalPath());
System.out.println(file4.exists()+":"+file4.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果如下:
true:D:\me\open\open-project\ResourceWeb\1.properties
true:D:\me\open\open-project\ResourceWeb\build\classes\2.properties
true:D:\me\open\open-project\ResourceWeb\build\classes\com\ghs\test\3.properties
true:D:\me\open\open-project\ResourceWeb\build\classes\com\ghs\test\sub\4.properties
细心的你肯定会发现,由于项目的性质不同,位置相同的文件,路径也会不一样。不过,如果你再细心一点,还会发现,这种不一样仅仅在于文件编译后的根目录。
所以,为了保证资源读取的统一性,Java提供了通用的资源读取方式,使得我们不用关心项目编译后文件的根目录。他们就是通过类、类加载器读取资源。
三、通过类/类加载器读取资源
同样是上面的Java项目,我们通过类加载器(ClassLoader)读取资源,代码如下:
public class ClassLoaderReaderTest {
public static void main(String[] args) {
try {
ClassLoader loader = ClassReaderTest.class.getClassLoader();
File file2 = new File(loader.getResource("2.properties").toURI());
System.out.println(file2.exists()+":"+file2.getCanonicalPath());
File file3 = new File(loader.getResource("com/ghs/test/3.properties").toURI());
System.out.println(file3.exists()+":"+file3.getCanonicalPath());
File file4 = new File(loader.getResource("com/ghs/test/sub/4.properties").toURI());
System.out.println(file4.exists()+":"+file4.getCanonicalPath());
File file1 = new File(loader.getResource("../1.properties").toURI());
System.out.println(file1.exists()+":"+file1.getCanonicalPath());
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
运行结果如下:
true:D:\me\open\open-project\ResourceTest\bin\2.properties
true:D:\me\open\open-project\ResourceTest\bin\com\ghs\test\3.properties
true:D:\me\open\open-project\ResourceTest\bin\com\ghs\test\sub\4.properties
java.lang.NullPointerException
at com.ghs.test.ClassReaderTest.main(ClassReaderTest.java:17)
我们会发现,通过ClassLoader读取资源的时候,当前路径就是项目文件编译后的根目录,对于普通Java项目而言,就是…/bin目录,对于web项目而言,就是…/build/classes目录。
但是,当我们在读取第一个文件的时候抛出了异常,这并不是因为我们的路径错了,而是因为1.properties不在类加载的范围之类。也就是说,类加载器能够读取到的资源仅仅局限于编译后的根目录。
下面,我们再使用类(Class)来读取资源,代码如下:
public class ClassLoaderReaderTest {
public static void main(String[] args) {
try {
Class clazz = ClassReaderTest.class;
File file2 = new File(clazz.getResource("/2.properties").toURI());
System.out.println(file2.exists()+":"+file2.getCanonicalPath());
File file3 = new File(clazz.getResource("3.properties").toURI());
System.out.println(file3.exists()+":"+file3.getCanonicalPath());
File file4 = new File(clazz.getResource("sub/4.properties").toURI());
System.out.println(file4.exists()+":"+file4.getCanonicalPath());
File file1 = new File(clazz.getResource("../1.properties").toURI());
System.out.println(file1.exists()+":"+file1.getCanonicalPath());
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
运行结果如下:
true:D:\me\open\open-project\ResourceTest\bin\2.properties
true:D:\me\open\open-project\ResourceTest\bin\com\ghs\test\3.properties
true:D:\me\open\open-project\ResourceTest\bin\com\ghs\test\sub\4.properties
java.lang.NullPointerException
at com.ghs.test.ClassReaderTest.main(ClassReaderTest.java:17)
当我们通过类加载资源时,当前路径就是当前类所在的路径,对上面的例子来说,就是MainTest.class所在的路径。当加载资源时,如果在路径前面加上”/”,就跟通过ClassLoader加载资源时完全一样的。
同样的,通过类加载资源时,仅限于项目编译后的根目录下的资源。