Commons Configuration之三Properties文件

Properties文件是流行的應用程序配置文件。固然,Commons Configuration支持這種格式並顯著加強了基礎的java.util.Properties類。本文介紹PropertiesConfiguration類的特性。注意PropertiesConfiguration是實現Configuration接口很是典型的例子,本文描述許多特性(例如,list處理或插值)其它配置類也支持。這是由於Commons Configuration附帶的大多數配置實現派生自實現這些特性的共同基類AbstractConfiguration。java

1    使用PropertiesConfiguration

讓咱們開始使用如下內容做爲名爲usergui.properties的簡單配置文件的內容:算法

# 定義GUI的屬性
colors.background = #FFFFFF
colors.foreground = #000080

window.width = 500
window.height = 300
跨域

加載改文件:數組

Configuration config = new PropertiesConfiguration("usergui.properties");
網絡

若是你不指定一個絕對路徑,文件將自動搜索如下位置:函數

  • 當前目錄工具

  • 用戶目錄佈局

  • 類路徑ui

替代使用須要一個文件名稱的構造函數,你能調用load()方法之一。有多種重載變體容許你從各類源加載配置。spa

配置文件加載以後,你能經過Configuration接口的方法訪問它的內容:

String backColor = config.getString("colors.background");
Dimension size = new Dimension(config.getInt("window.width"), config.getInt("window.height"));

2    包含

若是一個屬性名爲「include」,而且屬性的值是磁盤上的一個文件名,將被包括到配置中。下面是一個例子:

# usergui.properties

include = colors.properties
include = sizes.properties

# colors.properties

colors.background = #FFFFFF

3    List和數組

Commons Configuration有能力返回一個值列表。例如一個配置文件能包含逗號分隔的值的列表:

# chart colors
colors.pie = #FF0000, #00FF00, #0000FF

你不須要手動分隔值,你能直接檢索一個數組或java.util.List:

String[] colors = config.getStringArray("colors.pie");
List<Object> colorList = config.getList("colors.pie");

要麼,你能在你的配置文件中在多行使用相同鍵指定值列表:

# chart colors
colors.pie = #FF0000;
colors.pie = #00FF00;
colors.pie = #0000FF;

全部描述在AbstractConfiguration的關於list處理特性一樣適用於配置文件,包括改變list分隔符或禁用list處理。

4    保存

爲了保存你的配置,只需調用save()方法:

PropertiesConfiguration config = new PropertiesConfiguration("usergui.properties");
config.setProperty("colors.background", "#000000);
config.save();

你也能保存配置副本到其它文件:

PropertiesConfiguration config = new PropertiesConfiguration("usergui.properties");
config.setProperty("colors.background", "#000000);
config.save("usergui.backup.properties);// 保存到相對於usergui.properties的路徑

5    特殊字符和轉義

若是你須要在屬性中包含特殊字符像換行符、製表符或Unicode字符,你能使用與Java字符串相同的轉義字符指定它。list分隔符(默認是逗號),也能轉義:

key = This \n string \t contains \, escaped \\ characters \u0020

當處理包含反斜線字符(例如,Windows系統上的文件路徑)的元素列表時轉義規則會變得很複雜。首先要記住的是,爲了獲得一個反斜槓,你必須寫兩個:

config.dir = C:\\Temp\\

這個問題不是Commons Configuration致使的,而是關聯配置文件的標準格式。參考java.util.Properties的load()方法的Javadocs。如今若是你想要使用文件路徑定義一個列表,你可能會這麼寫:

# 定義文件目錄列表的錯誤的方式
config.dirs = C:\\Temp\\,D:\\data\\

正如註釋所述,這將不能工做。第一個目錄後面的反斜線解釋爲list分隔符的轉義字符。所以不是帶有兩個元素的list,僅僅是單個屬性值被定義——顯然不是指望的。爲了獲取正確的list後面的反斜線必須被轉義。經過複製它實現(是的,在配置文件中,意味着,如今咱們須要4個反斜線):

# 定義目錄列表的正確方式
config.dirs = C:\\Temp\\\\,D:\\data\\

所以,在屬性值中4個反斜線解釋爲一個反斜線轉移符並最終計算爲單個反斜線。當一個配置文件引用網絡共享名稱時產生其它問題。一般這些名稱以兩個反斜線開始,如此明顯的方式來定義這些屬性以下:

# 定義網絡共享的list的錯誤方式
config.dirs = \\\\share1,\\\\share2

不幸的是,這將不能工做,由於共享包含4個反斜線序列。所以當讀取config.dirs屬性的值一個list帶有兩個以一個反斜線開頭的元素。爲了解決這個問題,轉義符被重複——咱們如今須要8個反斜線:

# 定義網絡共享list的正確方式
config.dirs = \\\\\\\\share1,\\\\\\\\share2

顯而易見,轉義序列會變的很是複雜而且不可讀。在這種狀況下,推薦使用定義list的替代方式處理:使用相同的鍵屢次。在這種狀況下,沒有額外的反斜線轉義(除了一般須要複製配置文件)是必須的,由於沒有list分隔符被解析。

使用這種語法網絡共享list看起來以下所示:

# 定義網絡共享list的直接方式
config.dirs = \\\\share1
config.dirs = \\\\share2

6    佈局對象

每一個PropertiesConfiguration對象都關聯一個佈局對象,一個PropertiesConfigurationLayout類的實例。該佈局對象負責保存被加載配置文件的大部分結構。這意味着像註釋或空行在保存配置文件時與源文件相似(算法不是100%完美,但對於大多數用例應該足夠了)。

一般,開發不須要處理這些佈局對象。然而,有一些方法可能感興趣是否加強在配置文件的輸出控制是必須的。如下列表描述這些方法:

  • setComment():使用該方法指定屬性的註釋被設置。當存儲配置註釋,輸出屬性以前,後面有一個換行符。註釋能夠跨域多行;在這種狀況下換行字符「\n」必須做爲行分隔符。

  • setHeaderComment():使用setHeaderComment()配置文件的一個全局註釋被設置。該註釋寫在文件的最開始位置,後面是一個空行。

  • setBlankLinesBefore():該方法容許定義寫指定屬性以前的空行數。例如,它能用於分割屬性文件爲多個邏輯塊。

  • setSingleLine():若是屬性有多個值,使用setSingleLine()它能指定全部這些值應該寫成默認list分割的單行。它也可能寫該屬性的多個定義(例如,property=value1,property=value2的多行形式等)。經過PropertiesConfiguration支持,但當使用其它工具處理屬性文件時可能不會工做。

  • setForceSingleLine():相似於setSingleLine(),但設置全局單行標記。若是設置爲true,全部屬性值老是寫在單行中。

  • setGlobalSeparator():有可能須要定義屬性分隔符。這能使用setGlobalSeparator()完成。這是一個指定能用做分隔符的任意字符串。(注意:爲了產生有效的配置文件,只有字符=和:應該用做分隔符,前面和後面可使用或不使用空格),可是方法不強制。

  • setSeparator():該方法相似於setGlobalSeparator(),但容許設置特定屬性的屬性分隔符。

  • setLineSeparator():使用該法方法能指定行分隔符。默認使用特定平臺的行分隔符(例如,Unix是\n)。

PropertiesConfigurationLayout的默認設置選擇保留原始配置文件的大部分佈局。用上述方法能夠執行特定的佈局限制。

7    自定義配置讀取器和輸出器

有些狀況下更多的控制讀寫屬性文件的過程是必要的。例如,一個應用程序可能必須以特定格式處理一些遺留配置文件,PropertiesConfiguration不支持開箱即用,當必須不能修改。在這種狀況下,可能爲配置文件注入自定義讀取器和輸出器。

每一個默認配置文件經過(定義在PropertiesConfiguration中的)嵌套類PropertiesReader和PropertiesWriter讀取和寫出。這些類是常規讀取器和輸出器類(都派生自java.io包的基類)提供一些額外的方法更便利的處理配置文件。配置文件讀取器和輸出器的自定義實現必須擴展這些基類。

爲了安裝自定義屬性讀取器或輸出器,PropertiesConfiguration提供IOFactory接口(這也是一個嵌套類)。一個對象實現該接口存儲在每一個PropertiesConfiguration實例中。不管什麼時候,配置文件的讀取或寫出(例如,當load()或save()方法被調用時)IOFactory對象訪問建立屬性讀取器或寫出器。

IOFactory接口至關簡單;它定義方法建立一個屬性讀取器和屬性輸出器。當沒有使用PropertiesConfiguration指定IOFactory時,默認實現調用DefaultIOFactory。爲了更具體的討論,提供一個注入自定義屬性讀取器的例子。咱們加載一個配置文件的鍵必須包含空格。默認PropertiesConfiguration不支持。

Background Color = #800080
Foreground Color = #000080

第一步是建立一個能處理這一屬性的自定義屬性讀取器實現。類派生自PropertiesConfiguration.PropertiesReader並覆蓋parseProperty()方法:

public class WhitespacePropertiesReader extends PropertiesConfiguration.PropertiesReader
{
    public WhitespacePropertiesReader(Reader in, char delimiter)
    {
        super(in, delimiter);
    }
    
    /**
     * 解析帶有空格的屬性鍵的特殊算法。該方法每次從配置文件讀取沒有註釋的行調用。
     */
    protected void parseProperty(String line)
    {
        // 只在第一個「=」字符分隔行(在生產代碼中這應該更健壯)
        int pos = line.indexOf('=');
        String key = line.substring(0, pos).trim();
        String value = line.substring(pos + 1).trim();

        // 如今存儲屬性的鍵和值
        initPropertyName(key);
        initPropertyValue(value);
    }
}

注意調用initPropertyName()和initPropertyValue()方法。這致使解析操做被存儲。下一步是提供IOFactory接口的特定實現返回新的屬性讀取器類。咱們只但願替換屬性讀取器(和使用標準輸出器),能夠派生DefaultIOFactory實現,所以必須只覆蓋createPropertiesReader()方法。

public class WhitespaceIOFactory extends PropertiesConfiguration.DefaultIOFactory
{
    /**
     * 返回咱們制定的屬性讀取器
     */
    public PropertiesReader createPropertiesReader(Reader in, char delimiter)
    {
        return new WhitespacePropertiesReader(in, delimiter);
    }
}

最後咱們必須建立一個新的IOFactory實現的實例,並傳入PropertiesConfiguration對象。這必須在load()方法調用以前完成。所以咱們不能使用構造函數加載數據。設置配置對象的代碼應該以下所示:

PropertiesConfiguration config = new PropertiesConfiguration();config.setIOFactory(new WhitespaceIOFactory());config.setFile(...);  // 設置加載的文件config.load();

相關文章
相關標籤/搜索