Java 中获取资源文件输入流的方法

方法一:利用线程的类加载器。

1
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("jdbc.properties");

像 Tomcat 之类的容器,使用了自定义类加载器加载 jar 包。下面的方法可能会失效,但方法一仍然可用。

方法二:

1
InputStream is = ClassLoader.getSystemResourceAsStream("jdbc.properties");

方法三:

1
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");

方法四:

1
InputStream is = A.class.getClassLoader().getResourceAsStream("jdbc.properties");

前四种方法都是在类路径下查找文件。

方法五:(第五种方法是在 A.class 所在目录下查找文件。)

1
InputStream is = A.class.getResourceAsStream("jdbc.properties");

方法六:IO 流。

1
2
InputStream is = new FileInputStream("Module0/src/jdbc.properties")   // 或
InputStream is = new FileInputStream("D:/Module0/src/jdbc.properties")

第六种方法适用于资源文件不在类路径下的情况,例如,资源文件未打入 jar 包内,而是放在 jar 外。

ClassLoader 的 getResource 和 getResources 的区别

假设 a.jar 依赖 b.jar。它俩的类路径下都有一个 app.properties 文件。

在 a.jar 执行下面的代码,或在运行 a.jar 时,间接执行了 b.jar 中的下面代码,得到的都是 a.jar 的 app.properties 文件。

1
2
3
URL resource = ClassLoader.getSystemClassLoader().getResource("app.properties");
System.out.println(resource);
// 输出:a.jar!/app.properties

在 a.jar 执行下面的代码,或在运行 a.jar 时,间接执行了 b.jar 中的下面代码,会同时得到 a.jar 的 app.properties 文件,和 b.jar 的 app.properties 文件。

1
2
3
4
5
6
7
8
Enumeration<URL> resources = ClassLoader.getSystemClassLoader().getResources("app.properties");
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
System.out.println(url);
}
// 输出:
// a.jar!/app.properties
// b.jar!/app.properties

getResources 有一个差不多的流式 API:resources。

1
ClassLoader.getSystemClassLoader().resources("app.properties").forEach(System.out::println);

Properties

在 Java 中经常使用如下方法获取配置项:

新建一个 Properties 对象:

1
Properties props = new Properties();

使用 load() 方法,将文本文件中的内容加载到 props 对象中:

1
props.load(InputStream inStream);  // 入参是一个字节输入流对象

使用 getProperty() 方法,获取属性值:

1
2
3
props.getProperty("jdbc.driver") 
// 或:props.getProperty("jdbc.driver", "com.mysql.cj.jdbc.Driver")
// 第二个参数是在第一个参数找不到的情况下返回的值

ResourceBundle

Java 提供了一个 ResourceBundle 类。

该类有一个静态方法 getBundle(),可以用来获取 ResourceBundle 对象。

getBundle() 在类路径下查找资源。

例如,类路径下有如下文件:

1
2
3
4
config
|-- jdbc.properties // 这三个文件会被当做一个 ResourceBundle。
|-- jdbc_zh_CN.properties
|-- jdbc_en_US.properties

获取 ResourceBundle 对象:

1
ResourceBundle jdbc = ResourceBundle.getBundle("config.jdbc"); // 目录可以用句点或斜杠分隔

获取 ResourceBundle 对象后,可以使用它的 getString() 方法获取属性:

1
String driver = jdbc.getString("jdbc.driver");