讀取.properties配置文件在實際的開發中使用的很多,總結了一下,有以下幾種方法(僅僅是我知道的):
一、通過jdk提供的java.util.Properties類。
此類繼承自java.util.HashTable,即實現了Map接口,所以,可使用相應的方法來操作屬性文件,但不建議使用像put、putAll這兩個方法,因為put方法不僅允許存入String類型的value,還可以存入Object類型的。因此java.util.Properties類提供了getProperty()和setProperty()方法來操作屬性文件,同時使用store或save(已過時)來保存屬性值(把屬性值寫入.properties配置文件)。在使用之前,還需要加載屬性文件,它提供了兩個方法:load和loadFromXML。
load有兩個方法的重載:load(InputStream inStream)、load(Reader reader),所以,可根據不同的方式來加載屬性文件。
可根據不同的方式來獲取InputStream,如:
1、通過當前類加載器的getResourceAsStream方法獲取
- InputStream inStream = TestProperties.class.getClassLoader().getResourceAsStream("test.properties");
2、從文件獲取
- InputStream inStream = new FileInputStream(new File("filePath"));
3、也是通過類加載器來獲取,和第一種一樣
- InputStream in = ClassLoader.getSystemResourceAsStream("filePath");
4、在servlet中,還可以通過context來獲取InputStream
- InputStream in = context.getResourceAsStream("filePath");
5、通過URL來獲取
- URL url = new URL("path");
- InputStream inStream = url.openStream();
讀取方法如下:
- Properties prop = new Properties();
- prop.load(inStream);
- String key = prop.getProperty("username");
- //String key = (String) prop.get("username");
二、通過java.util.ResourceBundle類來讀取,這種方式比使用Properties要方便一些。
1、通過ResourceBundle.getBundle()靜態方法來獲取(ResourceBundle是一個抽象類),這種方式來獲取properties屬性文件不需要加.properties后綴名,只需要文件名即可。
- ResourceBundle resource = ResourceBundle.getBundle("com/mmq/test");//test為屬性文件名,放在包com.mmq下,如果是放在src下,直接用test即可
- String key = resource.getString("username");
2、從InputStream中讀取,獲取InputStream的方法和上面一樣,不再贅述。
- ResourceBundle resource = new PropertyResourceBundle(inStream);
注意:在使用中遇到的最大的問題可能是配置文件的路徑問題,如果配置文件入在當前類所在的包下,那么需要使用包名限定,如:test.properties入在com.mmq包下,則要使用com/mmq/test.properties(通過Properties來獲取)或com/mmq/test(通過ResourceBundle來獲取);屬性文件在src根目錄下,則直接使用test.properties或test即可。
這里主要是總結使用getResourceAsStream方法和InputStream流去讀取properties文件,使用getResourceAsStream方法去讀取properties文件時需要特別注意properties文件路徑的寫法
關於getClass().getClassLoader()
InputStream is = getClass().getClassLoader().getResourceAsStream("helloworld.properties");中getClass()和getClassLoader()都是什么意思呀.
If this object represents a primitive type or void, null is returned. Returns: 上面的英文可以用下面的話來理解: 裝載類的過程非常簡單:查找類所在位置,並將找到的Java類的字節碼裝入內存,生成對應的Class對象。Java的類裝載器專門用來實現這樣的過程,JVM並不止有一個類裝載器,事實上,如果你願意的話,你可以讓JVM擁有無數個類裝載器,當然這除了測試JVM外,我想不出還有其他的用途。你應該已經發現到了這樣一個問題,類裝載器自身也是一個類,它也需要被裝載到內存中來,那么這些類裝載器由誰來裝載呢,總得有個根吧?沒錯,確實存在這樣的根,它就是神龍見首不見尾的Bootstrap ClassLoader. 為什么說它神龍見首不見尾呢,因為你根本無法在Java代碼中抓住哪怕是它的一點點的尾巴,盡管你能時時刻刻體會到它的存在,因為java的運行環境所需要的所有類庫,都由它來裝載,而它本身是C++寫的程序,可以獨立運行,可以說是JVM的運行起點,偉大吧。在Bootstrap完成它的任務后,會生成一個AppClassLoader(實際上之前系統還會使用擴展類裝載器ExtClassLoader,它用於裝載Java運行環境擴展包中的類),這個類裝載器才是我們經常使用的,可以調用ClassLoader.getSystemClassLoader() 來獲得,我們假定程序中沒有使用類裝載器相關操作設定或者自定義新的類裝載器,那么我們編寫的所有java類通通會由它來裝載,值得尊敬吧。AppClassLoader查找類的區域就是耳熟能詳的Classpath,也是初學者必須跨過的門檻,有沒有靈光一閃的感覺,我們按照它的類查找范圍給它取名為類路徑類裝載器。還是先前假定的情況,當Java中出現新的類,AppClassLoader首先在類傳遞給它的父類類裝載器,也就是Extion ClassLoader,詢問它是否能夠裝載該類,如果能,那AppClassLoader就不干這活了,同樣Extion ClassLoader在裝載時,也會先問問它的父類裝載器。我們可以看出類裝載器實際上是一個樹狀的結構圖,每個類裝載器有自己的父親,類裝載器在裝載類時,總是先讓自己的父類裝載器裝載(多么尊敬長輩),如果父類裝載器無法裝載該類時,自己就會動手裝載,如果它也裝載不了,那么對不起,它會大喊一聲:Exception,class not found。有必要提一句,當由直接使用類路徑裝載器裝載類失敗拋出的是NoClassDefFoundException異常。如果使用自定義的類裝載器loadClass方法或者ClassLoader的findSystemClass方法裝載類,如果你不去刻意改變,那么拋出的是ClassNotFoundException。 這里jdk告訴我們:如果一個類是通過bootstrap 載入的,那我們通過這個類去獲得classloader的話,有些jdk的實現是會返回一個null的,比如說我用 new Object().getClass().getClassLoader()的話,會返回一個null,這樣的話上面的代碼就會出現NullPointer異常.所以保險起見我們最好還是使用我們自己寫的類來獲取classloader("this.getClass().getClassLoader()“),這樣一來就不會有問題。 |