Java加載資源文件的兩種方法


處理配置文件對於Java程序員來說再常見不過了,不管是Servlet,Spring,抑或是Structs,都需要與配置文件打交道。Java將配置文件當作一種資源(resource)來處理,並且提供了兩個類來讀取這些資源,一個是Class類,另一個是ClassLoader類。

  當我們自己的程序需要處理配置文件時(比如xml文件或properties文件),通常會遇到兩個問題:

  (1)我的配置文件應該放在哪里?

  (2)怎么我的配置文件找不到了?

  在了解了Java加載資源文件的機制后,以上這兩個問題便迎刃而解了。

  對於第一個問題,答案是:請將你的資源文件放在classpath里,如果資源文件在jar中,請將該jar文件也加到classpath里面。

  對於第二個問題,就得看你是使用的是哪個類(Class還是ClassLoader)來加載資源文件了,所以接下來分別討論一下Class類和ClassLoader類對於資源文件的加載機制。

  (一)用Class類加載資源文件

  通過調用Class類的getResourceAsStream方法來加載資源文件:

  public InputStream getResourceAsStream(String pathToConfigFile);

  該方法接收一個String類型的參數(pathToConfigFile)來表示資源文件的地址,如果加載成功,則返回該資源文件的輸入流(InputStream),如果失敗,則返回null。重要的是,在傳入pathToConfigFile參數時,有兩種方式,第一種方式為絕對定位方式,即pathToConfigFile以"/"開頭,此時Java以classpath為根目錄,直接加上pathToConfigFile來搜索資源文件。第二種方式為相對定位方式,即pathToConfigFile不以"/"開頭,此時資源文件的全路徑應該為:調用getResourceAsStream方法的類的package路徑加上pathToConfigFile。(在將package轉為目錄時將"."變成"/")

  舉個例子,在IntelliJ Idea中創建一個java工程,目錄結構如下:

  該工程里有兩個resources文件夾,一個位於davenkin文件夾下,一個直接位於src文件夾下。第一個resources文件夾下有一個config.properties文件,其內容為:

 

name = ConfigUnderDavenkin

 

  第二個resources文件夾下也有一個config.properties文件,其內容為:

 

 

name = ConfigUnderSrc

在davenkin包下定義ResourceLoader.java來加載資源文件:

 

package davenkin;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class ResourceLoader
{
    public static void main(String[] args) throws IOException
    {
        ResourceLoader resourceLoader = new ResourceLoader();
        resourceLoader.loadProperties1();

    }

    public void loadProperties1() throws IOException
    {
        InputStream input = null;
        try
        {
            input = Class.forName("davenkin.ResourceLoader").getResourceAsStream("/resources/config.properties");

            //also can be this way:
            //input = this.getClass().getResourceAsStream("/resources/config.properties");
        } catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        printProperties(input);
    }

    private void printProperties(InputStream input) throws IOException
    {
        Properties properties = new Properties();
        properties.load(input);
        System.out.println(properties.getProperty("name"));
    }
}

 

  輸出結果為第二個resources文件夾下config.properties的內容:

 

ConfigUnderSrc

 

  原因在於(請注意ReourceLoader.java文件中的紅色部分):我們給出的資源文件路徑(/resources/config.properties)以"/"開頭,即使用的是絕對定位方式,所以找到的是直接在classpath下的resources文件夾。如果去掉資源文件文件路徑前的"/",則采用的是相對定位方式,此時應該輸出davenkin/resources/config.properties文件的內容。

  (二)用ClassLoader類加載資源文件

  ClassLoader類也提供和Class類相同的加載方法:

  public InputStream getResourceAsStream(String pathToConfigFile);

  用ClassLoader加載配置文件時,pathToConfigFile均不能以"/"開頭,在查找時直接在classpath下進行查找。Class類在查找資源文件時,也是代理(delegate)給ClassLoader完成查找功能的,請參考Java官方文檔。

在使用Class和ClassLoader加載資源文件時,有幾種區別細微的方法,修改ResourceLoader.java文件如下:

 

package davenkin;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class ResourceLoader
{
    public static void main(String[] args) throws IOException
    {
        ResourceLoader resourceLoader = new ResourceLoader();
        resourceLoader.loadProperties1();
        resourceLoader.loadProperties2();
        resourceLoader.loadProperties3();
        resourceLoader.loadProperties4();
        resourceLoader.loadProperties5();
        resourceLoader.loadProperties6();
    }

    public void loadProperties1() throws IOException
    {
        InputStream input = null;
        try
        {
            input = Class.forName("davenkin.ResourceLoader").getResourceAsStream("/resources/config.properties");
        } catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        printProperties(input);
    }

    public void loadProperties2() throws IOException
    {
        InputStream input = null;

        input = this.getClass().getResourceAsStream("/resources/config.properties");
        printProperties(input);
    }

    public void loadProperties3() throws IOException
    {
        InputStream input = this.getClass().getResourceAsStream("resources/config.properties");
        printProperties(input);
    }

    public void loadProperties4() throws IOException
    {
        InputStream input = this.getClass().getClassLoader().getResourceAsStream("resources/config.properties");
        printProperties(input);
    }

    public void loadProperties5() throws IOException
    {
        InputStream input = ClassLoader.getSystemResourceAsStream("resources/config.properties");
        printProperties(input);
    }

    public void loadProperties6() throws IOException
    {
        InputStream input = ClassLoader.getSystemClassLoader().getResourceAsStream("resources/config.properties");

        printProperties(input);
    }

    private void printProperties(InputStream input) throws IOException
    {
        Properties properties = new Properties();
        properties.load(input);
        System.out.println(properties.getProperty("name"));
    }
}

 

  以上程序輸出結果為(請仔細揣摩,稍不小心(比如多加了一個"/"或少加了一個"/"),就會報NullPointerException異常,表明你的資源文件沒有找到):

 

ConfigUnderSrc
ConfigUnderSrc
ConfigUnderDavenkin
ConfigUnderSrc
ConfigUnderSrc
ConfigUnderSrc


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM