小瓜牛漫谈 — 获取资源文件

在开发 WEB 运用的时候, 我常常忍受不了看到在 src 根目录底下放一堆配置文件, 在 WEB-INF 下又放一堆配置文件,

在某个比较隐藏的地方又存放了一些个配置文件, 这样总感觉很凌乱, 不方便也不好管理。

我更加倾向于使用 Maven 式的风格, 尽可能的通过 Source Folder 或 package 来管理项目的配置文件。

例如:

或者

其中, 资源文件放在 resources 根目录底下与放在 src 根目录底下是等效的, 因为在 Web Project 里面,

凡是Source Folder 里面的东西最终都会编译到本地目录的 WebRoot/WEB-INF/classes 底下。

[ java 文件编译成了 .class 字节码文件存在于 classes, 非 java 文件则是直接拷贝搬过去。]

[如果是 Java Project, 则存在于项目所在的本地目录的 bin 目录底下, 实际上它们都是项目的类搜索路径。]

另外, 放在package 里面的资源文件, 同样也会被编译(非 java 文件直接拷贝)到 classes 中, 存在于的目录与包名相对应。

由于资源文件放在 resources 与放在 src 底下效果是一致的, 所以接下主要是谈谈资源文件放在 package 下的情况。

以上面贴出来的右边的图为例, 资源文件放在 package 里面, 有时候常常需要自己去读取配置文件, 本人常用的手段有:

1> 通过 Class 类的 getResourceAsStream(String name) 方法来构造 InputStream。其中, name 的写法有两种: 绝对路径和相对路径。

1.1> 绝对路径:

app() throws IOException {2InputStream in = getClass().getResourceAsStream(“/min/snail/resources/config.properties”);}

绝对路径的写法是以 ‘/’ 开头: /modified_package_name/name

modified_package_name 指的是修正后的包名, 简单的理解就是包名, name 是资源文件的名称(包括后缀名)。

[包名中的 ‘.’ 分隔符在转换成路径来使用的时候, 通通需要将 ‘.’改写成 ‘/’ 或 ‘\\’, 以下说的包名皆是这个意思。]

1.2> 相对路径:

app() throws IOException {2InputStream in = getClass().getResourceAsStream(“./resources/config.properties”);}

其中, app() 方法是写在 min.snail.Application 类里面。

‘.’ 代表的是当前 Class 对象的包名(以绝对路径形式), 在示例中相当于 /min/snail, 然后拼上后面的 resources/config.properties 就能找到资源文件。

也可以将 ‘.’ 省略, 相对路径直接写成:

app() throws IOException {2InputStream in = getClass().getResourceAsStream(“resources/config.properties”);}

1.3> 假设 app() 方法不是写在 min.snail.Application 类, 而是写在 min.snail.copy.Application 类里面, 那么相对路径是:

app() throws IOException {2InputStream in = getClass().getResourceAsStream(“./../resources/config.properties”);3 System.out.println(in.available());4 }

根据 1.2 的分析, 这里的 ‘.’ 表示的是: /min/snail/copy

‘..’ 相信大家都知道是什么意思, 就是返回到上一级目录, 当前目录是 /min/snail/copy, 那么上一级目录就是 /min/snail

再拼上后面的 /resources/config.properties 就是: /min/snail/resources/config.properties

或者直接写成:

app() throws IOException {2InputStream in = getClass().getResourceAsStream(“../resources/config.properties”);3 System.out.println(in.available());4 }

通过Class 类的 getResourceAsStream(String name) 局限性比较大, 因为只能利用它来构造输入流, 如果想构造输出流, 那么这种方法就显得无能为力了。

2> 通过 FileInputStream(String name) 来构造 InputStream。

FileInputStream(String name) 在底层其实是通过 FileInputStream(File file) 构造方法来实现的, 因此会去调 new File(String pathname)。

首先是要知道如何去写 name 的值, 为解决这一问题,下面是借助 File 类来帮助理解:

示例一:

app() {2File file = new File(“”);System.out.println(file.isFile()); System.out.println(file.isDirectory()); System.out.println(file.getAbsolutePath()); }

示例二:

app() {2File file = new File(“.”);System.out.println(file.isFile()); System.out.println(file.isDirectory()); System.out.println(file.getAbsolutePath()); }

示例一在构造 File 对象的时候传的是空串, 因此打印 file 不存在, file 不是一个文件, 也不是一个目录,

但此时 file 取得的绝对路径是项目所在磁盘的本地目录的路径;

示例二中, 结合示例一, 空串能取得项目所在本地磁盘的绝对路径, ‘.’ 代表的是当前目录, 因此打印输出 file存在,

file 不是一个文件而是一个目录, file 取得的绝对路径是项目所在磁盘的本地目录的路径后面加了个 ‘.’, 这里的 ‘.’ 对路径是

没有影响的, 它代表的是它前面的那段串所构成的路径。

[File(String pathname) 构造方法在底层是借助 native 方法来实现的, 我追踪不到源码, 因此,

以上关于File 构造方法中的 ‘.’ 的理解纯属个人看法, 如果有说的不对的地方, 欢迎广大网友指出。]

2.1> 从上面可以看出, 空串 “” 和 “.” 取得的绝对路径都是项目的根目录所在的路径, 因此, 如何构造 FileInputStream(String name) 就有招可支了:

app() throws IOException {2InputStream in = new FileInputStream(“./src/min/snail/resources/config.properties”);}

因为 config.properties 文件就是存放在项目所在目录的 src/min/snail/resources/ 下, 而 ‘.’ 能取到项目根目录的绝对路径。

也可以直接写成:

app() throws IOException {2InputStream in = new FileInputStream(“src/min/snail/resources/config.properties”);}

因为空串也能取得项目根目录的绝对路径, 我是这么理解的, 如果有说的不对的地方, 同样, 欢迎广大网友指出。

需要注意的是, 不能以 ‘/’ 开头, 例如:

new FileInputStream(“/src/min/snail/resources/config.properties”);

new FileInputStream(“/./src/min/snail/resources/config.properties”);

上面的两种写法是错误的, 运行时程序会抛出 java.io.FileNotFoundException。

因为 FileInputStream(String name), 底层会去调 new File(name), 而 File(“/”) 得到的绝对路径是系统盘的根目录:

可以提高你的水平。(戏从对手来。

小瓜牛漫谈 — 获取资源文件

相关文章:

你感兴趣的文章:

标签云: