http://gceclub.sun.com.cn/Java_Docs/jdk6/html/zh_CN/api/java/util/ResourceBundle.html
ResourceBundle类
ResourceBundle类主要作用是读取属性文件,读取属性文件时可以直接指定属性文件的名称(指定名称时不需要文件的后缀),也可以根据Locale所指定的区域码来选取指定的资源文件,ResourceBundle类的常用方法如表11-4所示。
表11-4 ResourceBundle类的常用方法
序号 | 方 法 | 类型 | 描 述 |
1 | public static final ResourceBundle getBundle (String baseName) | 普通 | 取得ResourceBundle的实例, 并指定要操作的资源文件名称 |
2 | public static final ResourceBundle getBundle (String baseName,Locale locale) | 普通 | 取得ResourceBundle的实例, 并指定要操作的资源文件名称和区域码 |
3 | public final String getString(String key) | 普通 | 根据key从资源文件 中取出对应的value |
如果现在要使用ResourceBunlde对象,则肯定直接通过ResourceBundle类中的静态方法getBundle()取得。下面通过一个范例简单介绍ResourceBundle类的使用。
范例:通过ResourceBundle取得资源文件中的内容
(1)定义资源文件:Message.properties
- info = HELLO
(2)从资源文件中取得内容
- import java.util.ResourceBundle;
- public class InterDemo01 {
- public static void main(String[] args) {
- ResourceBundle rb = ResourceBundle. getBundle("Message") ;// 找到资
- 源文件
- System.out.println("内容:" + rb. getString("info")) ;// 从资源文件中
- 取得内容
- }
- }
程序运行结果:
内容:HELLO
从以上程序中可以发现,程序通过资源文件中的key取得了对应的value。
Java国际化程序实现
11.3.3节中的代码演示了ResourceBundle类的作用,下面就在程序中结合Locale类一起完成一个国际化的程序开发。
下面完成一个简单的国际化操作,可以根据Locale所选择的国家不同,输出不同国家的"你好!"。
中文:你好!
英语:Hello!
法语:Bonjour!
首先根据不同的国家代码建立不同的属性文件,建立的属性文件与生成的*.class保存在同一个文件夹中。因为现在程序要使用的有3种语言,所以要定义3种属性文件,在属性文件定义时必须按照"名称_国家代码"的形式命名,即所有相关的属性文件的名称全部一样,只有国家代码不一样,代码如下所示。
(1)中文的属性文件:Message_zh_CN.properties
- info = \u4f60\u597d\uff01
实际上以上的信息就是中文的"你好!",在属性文件的操作中是不能直接写入中文的,就算是写入了中文,读取出来的也必然是乱码,因此必须将相应的中文变为Unicode编码才可以,要成功地将一个中文编码变为Unicode编码,可以直接在运行处执行"native2ascii.exe"命令,输入相应的中文之后会自动将其进行编码。
(2)英语的属性文件:Message_en_US.properties
- info = Hello!
(3)法语的属性文件:Message_fr_FR.properties
- Info = Bonjour!
- 通过Locale类和ResourceBundle类读取属性文件的内容,代码如下。
- import java.util.Locale;
- import java.util.ResourceBundle;
- public class InterDemo02 {
- public static void main(String[] args) {
- Locale zhLoc = new Locale("zh", "CN"); // 表示中国地区
- Locale enLoc = new Locale("en", "US"); // 表示美国地区
- Locale frLoc = new Locale("fr", "FR"); // 表示法国地区
- // 找到中文的属性文件
- ResourceBundle zhrb = ResourceBundle.getBundle("Message",zhLoc) ;
- // 找到英语的属性文件
- ResourceBundle enrb = ResourceBundle.getBundle("Message",enLoc) ;
- // 找到法语的属性文件
- ResourceBundle frrb = ResourceBundle.getBundle("Message",frLoc) ;
- // 依次读取各个属性文件的内容,通过键值读取,此时的键值名称为"info"
- System.out.println("中文:" + zhrb.getString("info")) ;
- System.out.println("英语:" + enrb.getString("info")) ;
- System.out.println("法语:" + frrb.getString("info")) ;
- }
- }
程序运行结果:
中文:你好!
英语:Hello!
法语:Bonjour!
从以上程序中可以清楚地发现,根据Locale所指定的国家不同,读取的资源文件也不同,这样也就实现了国际化程序。
处理动态文本(1)
在以上程序中,所有资源内容都是固定的,但是输出的消息中如果包含了一些动态文本,则必须使用占位符清楚地表示出动态文本的位置,占位符使用"{编号}"的格式出现。使用占位符之后,程序可以直接通过MessageFormat对信息进行格式化,为占位符动态设置文本的内容。
MessageFormat是Format类的子类,Format类主要实现格式化操作,除了MessageFormat子类外,Format还有NumberFormat、DateFormat两个子类,这两个子类的使用在本章的后面部分均有讲解,读者先来了解MessageFormat类的作用。
U提示:关于Format子类的说明。
在进行国际化操作时,不光只有文字需要处理,实际上数字的显示、日期的显示都要符合各个区域的要求,读者可以通过"区域和语言选项"对话框观察到这一点,如图11-5所示。
![]() |
图11-5 控制面板中的区域和语言选项 |
在这里要同时改变的有数字、货币、时间等,所以Format类提供了3个子类,即MessageFormat、DateFormat、NumberFormat。
例如,现在要输出的信息(以中文为例)是"你好,xxx!",其中,xxx的内容是由程序动态设置的,所以,此时修改之前的3个属性文件,让其动态地接收程序的3个文本。
(1)中文的属性文件:Message_zh_CN.properties
- info = \u4f60\u597d\uff0c{0}\uff01
以上信息就是中文的"你好,{0}!"。
(2)英语的属性文件:Message_en_US.properties
- info = Hello,{0}!
(3)法语的属性文件:Message_fr_FR.properties
- info = Bonjour,{0}!
在以上3个属性文件中,都加入了"{0}",表示一个占位符,如果有更多的占位符,则直接在后面继续加上"{1}"、"{2}"即可。
然后继续使用之前的Locale类和ResourceBundle类读取资源文件的内容,但是读取之后的文件因为要处理占位符的内容,所以要使用MessageFormat类进行处理,主要使用以下方法:
- public static String format(String pattern,Object…arguments)
以上方法中第1个参数表示要匹配的字符串,第2个参数"Object…arguments"表示输入参数可以任意多个,没有个数的限制。
范例:使用MessageFormat格式化动态文本
- import java.text.MessageFormat;
- import java.util.Locale;
- import java.util.ResourceBundle;
- public class InterDemo03 {
- public static void main(String[] args) {
- Locale zhLoc = new Locale("zh", "CN"); // 表示中国地区
- Locale enLoc = new Locale("en", "US"); // 表示美国地区
- Locale frLoc = new Locale("fr", "FR"); // 表示法国地区
- // 找到中文的属性文件
- ResourceBundle zhrb =ResourceBundle.getBundle("Message",zhLoc) ;
- // 找到英语的属性文件
- ResourceBundle enrb =ResourceBundle.getBundle("Message",enLoc) ;
- // 找到法语的属性文件
- ResourceBundle frrb =ResourceBundle.getBundle("Message",frLoc) ;
- // 依次读取各个属性文件的内容,通过键值读取,此时的键值名称为"info"
- String str1 = zhrb.getString("info") ;
- String str2 = enrb.getString("info") ;
- String str3 = frrb.getString("info") ;
- System.out.println("中文:" + MessageFormat.format(str1,"李兴华")) ;
- System.out.println("英语:" + MessageFormat.format(str2,"LiXingHua")) ;
- System.out.println("法语:" + MessageFormat.format(str3,"LiXingHua")) ;
- }
- }
程序运行结果:
中文:你好,李兴华!
英语:Hello,LiXingHua!
法语:Bonjour,LiXingHua!
以上程序代码通过MessageFormat.format()方法设置动态文本的内容,如果有更多的占位符则可按照图11-6所示设置多个参数。
![]() |
(点击查看大图)图11-6 为多个占位符设置多个动态文本 |
处理动态文本(2)
U提示:Java新特性--可变参数传递中可以接收多个对象。
在方法传递参数时可以使用如下的形式:
- 返回值类型 方法名称(Object…args)
表示方法可以接收任意多个参数,然后按照数组的方式输出即可,代码如下所示。
范例:测试参数传递
- public class InterDemo04 {
- public static void main(String[] args) {
- System.out.print("第一次运行:");
- fun("LXH","Li","李兴华") ; // 传入3个参数
- System.out.print("\n第二次运行:");
- fun("MLDN") ; // 传入1个参数
- }
- public static void fun(Object...args){ // 可以输入任意多个数据,使用数组
- 表示
- for(int i=0;i<args.length;i++){
- System.out.print(args[i] + "、");
- }
- }
- }
程序运行结果:
第一次运行:LXH、Li、李兴华、
第二次运行:MLDN、
从程序的运行结果中可以发现,无论在方法调用时输入多少个参数,方法都可以接收,接收参数之后可以直接以数组的形式对参数进行输出。
在其他的资料中读者也可能看到使用数组的方式向可变参数传递内容,代码如下所示。
范例:使用数组传递参数
- package org.lxh.demo11.interdemo;
- public class InterDemo05 {
- public static void main(String[] args) {
- System.out.print("第一次运行:");
- Object[] arg1 = {"LXH","Li","李兴华"} ; // 对象数组,保存所有具体内容
- fun(arg1) ; // 传入3个参数
- System.out.print("\n第二次运行:");
- Object[] arg2 = {"MLDN"} ;
- fun(arg2) ; // 传入1个参数
- System.out.print("\n第三次运行:");
- Object[] arg3 = {} ;
- fun(arg3) ; // 没有参数传入
- }
- public static void fun(Object...args){ // 可变参数
- for(int i=0;i<args.length;i++){
- System.out.print(args[i] + "、");
- }
- }
- }
程序运行结果:
第一次运行:LXH、Li、李兴华、
第二次运行:MLDN、
第三次运行:
从运行结果来看,两种方式是一样的,没有任何的区别,读者可以根据个人喜好来选择,并没有强制性的规定。