如果一個字符串文本中包含了多個與國際化相關的數據,可以使用MessageFormat類對這些數據進行批量處理。
例如:
在2016年1月9日的時候,一場台風導致了500間房屋的摧毀和¥1000000元人民幣的損失。
在上面這句話中,包含了時間、數字和貨幣等多個與國家化相關的數據,已經用下划線標出,而我們可以使用MessageFormat對這句話中多個數據進行批量處理。
要想使用MessageFormat進行批量處理,就要使用到占位符,用占位符替換上面的數據(不需要寫死的數據或者與國際化相關的數據)。占位符由花括號{}和在花括號中的數字組成,數字代表這是第幾個占位符,現在我們對上面的那個示例使用占位符:
在{0}的時候,一場台風導致了{1}間房屋的摧毀和{2}元人民幣的損失。
經過占位符修改的字符串文本也稱為模式字符串,如上面這句話,有了模式字符串后,我們需要一個對象數組來指定每個占位符對應的數據,在數組中的位置就對應着其相同位置的占位符。現在擁有了模式字符串和對象數組后,我們就可以使用MessageFormat對象的format方法,將數組中的數據一一對應到占位符上了。
占位符由三種書寫格式:
① {index}:index為0~9之間的數字,對應對象數組中的位置。
② {index,formatType}:index為0~9之間的數字,formatType為參數的格式化類型
③ {index,formatType,formatStyle}:formatStyle為參數的格式化樣式。
有關占位符的使用稍后說明。
注:在創建MessageFormat對象時可以直接將模式字符串以參數傳入構造器,也可以直接使用MessageFormat的靜態方法format(String pattern , Object …params)只執行一次。
例1:

1 String pattern = "在{0}的時候,一場台風導致了{1}間房屋的摧毀和{2}元人民幣的損失。"; 2 Object[] params = {new Date(),500,1000000}; 3 MessageFormat mf = new MessageFormat(pattern); 4 String content = mf.format(params); 5 System.out.println(content);
上述代碼等同於:

1 String pattern = "在{0}的時候,一場台風導致了{1}間房屋的摧毀和{2}元人民幣的損失。"; 2 Object[] params = {new Date(),500,1000000}; 3 String content = MessageFormat.format(pattern, params); 4 System.out.println(content);
輸出:
結果就是:在16-1-9 下午7:56的時候,一場台風導致了500間房屋的摧毀和1,000,000元人民幣的損失。
可以看到在對應的占位符上,我們用對象數組中的內容替代了占位符。但是似乎和最開始我們規定的字符串文本有點不同?
最開始我們規定的文本:
在2016年1月9日的時候,一場台風導致了500間房屋的摧毀和¥1,000,000元人民幣的損失。
例1占位符被替代后的文本:
在16-1-9 下午7:56的時候,一場台風導致了500間房屋的摧毀和1,000,000元人民幣的損失。
可以看到日期格式和貨幣格式跟我們規定的不同,而這一點可以想到前一篇博客我們學到的DateFormat和NumberFormat中可以指定日期/時間或貨幣的輸出格式。而這里我們要先了解下占位符:
占位符有三種書寫格式:
① {index}:index為0~9之間的數字,對應對象數組中的位置。
② {index,formatType}:index為0~9之間的數字,formatType為參數的格式化類型
③ {index,formatType,formatStyle}:formatStyle為參數的格式化樣式,該樣式必須是格式化類型相匹配的合法模式,或表示合法模式的字符串。
在Java的API關於MessageFormat中,已經定義了formatType和formatStyle能使用的參數有哪些:
通過上圖我們就明白了formatType和formatStyle到底能使用哪些值,比如formatType如果我選了“date”,就代表該占位符是一個日期,那么可以指定formatStyle(使用占位符第三種書寫方式),也就是DateFormat的日期顯示格式;當然也可以不指定(使用占位符第二種書寫方式),那么該DateFormat就采用默認(MEDIUM)的日期顯示格式。如果formatType選擇為“number”也是一樣的道理。如果對DateFormat和NumberFormat不熟悉的可以看上一篇博客《國際化之DateFormat、NumberFormat》 。
總結:
formatType如果使用“date”,那么就是采用DateFormat類的getDateInstance方法獲取只關於日期的DateFormat類實例對象,根據formatStyle來獲取日期輸出格式。
formatType如果使用“time”,那么就是采用DateFormat類的getTimeInstance方法獲取只關於時間的DateFormat類實例對象,根據formatStyle來獲取時間輸出格式。
formatType如果使用“number”,如果也指定了formatStyle為“currency”,那么就是調用了NumberFormat的getCurrencyInstance方法獲取有關於貨幣格式的NumberFormat類對象。
當然通過上圖還可以獲得很多對象,還有其他類型的格式轉換器類,比如SimpleDateFormat等等,具體根據上圖和實際情況滿足需求即可。
例2:

1 String pattern = "在{0,date,long}的時候,一場台風導致了{1}間房屋的摧毀和{2,number,currency}元人民幣的損失。"; 2 Object[] params = {new Date(),500,1000000}; 3 4 String content = MessageFormat.format(pattern, params); 5 System.out.println(content);
輸出:
結果就是:在2016年1月9日的時候,一場台風導致了500間房屋的摧毀和¥1,000,000.00元人民幣的損失。
可以看到這就跟我們的最開始定義的字符串文本相同了。
占位符在框架中是經常被使用到的,當然占位符一般不會在程序代碼中被使用,而是在資源文件properties被使用,這是想Struts2這樣的框架經常被使用到的,結合前兩篇的《國際化之ResourceBundle》,如果模式字符串在properties中使用,那么我們需要通過ResourceBundle通過資源文件的基名獲取對象,並使用getString方法獲取模式字符串,最后只要使用MessageFormat像上面一樣處理就行了。
例3:
在工程中用一個包來封裝一組資源包,該組資源包中默認的資源配置文件基名為“MessageResource”,同時配有中文和英文兩個資源配置文件,如下圖所示:
在默認的資源文件“MessageResource.properties”中定義的內容如下:
在中文資源文件“MessageResource_zh.properties”中定義的內容如下:
英文資源文件和默認資源文件中的內容是一樣的,這里就不再貼出。
因為我們將資源文件放在包中,所以基名應該包括包名,這一點在博文《《國際化之ResourceBundle》中已經說明。
在程序中代碼如下:

1 ResourceBundle bundle = ResourceBundle.getBundle("com.fjdingsd.resource.MessageResource",Locale.CHINA); 2 String pattern = bundle.getString("message"); //獲取模式字符串 3 Object[] params = {new Date(),500,10000000}; 4 5 String content = MessageFormat.format(pattern, params); 6 System.out.println(content);
輸出:在16-1-9 下午8:59的時候,一場台風導致了500間房屋的摧毀和10,000,000元人民幣的損失。
注意:⑴ 這里占位符對應的地方格式並不友好,這是因為占位符沒有使用特定的格式,參見例2。
⑵ 在ResourceBundle獲取對象中使用到了Locale是以中國的形式,因此最后輸出的是中文,如果想以美國作為Locale,那么將會輸出英文:
修改代碼為:

1 ResourceBundle bundle = ResourceBundle.getBundle("com.fjdingsd.resource.MessageResource",Locale.US); 2 String pattern = bundle.getString("message"); //獲取模式字符串 3 Object[] params = {new Date(),500,10000000}; 4 5 String content = MessageFormat.format(pattern, params); 6 System.out.println(content);
輸出:On 16-1-9 下午9:03, a typhoon destory 500 houses and caused 10,000,000 of damage.
看上去似乎很正確,但是在這些英文中出現了中文,而且是在占位符對應的地方,說明我們還未將MessageFormat對象的代表的語言國家環境修改,最終代碼如下:

1 ResourceBundle bundle = ResourceBundle.getBundle("com.fjdingsd.resource.MessageResource",Locale.US); 2 String pattern = bundle.getString("message"); //獲取模式字符串 3 Object[] params = {new Date(),500,10000000}; 4 5 MessageFormat mf = new MessageFormat(pattern, Locale.US); 6 String content = mf.format(params); 7 System.out.println(content);
輸出:On 1/9/16 9:07 PM, a typhoon destory 500 houses and caused 10,000,000 of damage.