1. 程序中的一些文字信息可以将之定义在一个属性文件中,而不定要写在程序代码中,这样在日后想更改文字信息时,只要更改文本文件的内容而不用重新编译程序,就可以在程序运行时显示不同的信息。
2.使用ResourceBundle:
对于程序中日后可能变动的文字信息,可以考虑将信息移到程序之外。方法是用java.util.ResourceBundle来作信息绑定,首先要准备一个.properties文件,例如messages.properties,而文件的内容如下:
onlyfun.caterpillar.welcome = Hello
onlyfun.caterpillar.name = World
.properties文件必须放置在Classpath的路径设定下,文件中编写的是键、值配对,之后在程序中可以使用键来取得对应的值。如下示例:
package ysu.hxy; import java.util.ResourceBundle; public class ResourceBundleDemo { public static void main(String[] args) { //绑定messages.properties ResourceBundle resource = ResourceBundle.getBundle("messages"); //取得对应信息 System.out.print(resource.getString("onlyfun.caterpillar.welcome")); System.out.print(resource.getString("onlyfun.caterpillar.name")+"!"); } }
ResourceBundle的静态getBundle()方法会取得一个ResourceBundle的实例,所给定的参数名称是信息文件的主文件名,getBundle()会自动找到对应的.properties文件。取得了ResourceBundle实例后,可以使用getString()指定键来取得文件中对应的值。执行结果如下:
D:\Java_Test>java ysu.hxy.ResourceBundleDemo
HelloWorld!
这样的话如果日后想要改变显示的信息,只要改变.properties文件的内容就可以了。例如若将message.properties的文件内容改为:
onlyfun.caterpillar.welcome = Hello
onlyfun.caterpillar.name = hxy
无需重新编译此范例,直接执行程序,输出信息如下:
D:\Java_Test>java ysu.hxy.ResourceBundleDemo
Hellohxy!
3.格式化信息
程序在运行的过程中,有些信息可能必须动态决定,而之前介绍信息绑定时,.properties文件中的信息则是静态的,也就是固定的文字内容,除非修改.properties文件内容并重新启动程序,否则一些信息内容无法随着程序动态显示。
可以使用java.text.MessageFormat类来辅助信息的格式化,MessageFormat接受一个字符串模式(Pattern)指定。对于文字信息中可能变动的部分,可以使用参数索引(Argument Index)先占住文字位置,参数索引是{0}--{9}的非负整数,之后在使用MessageFormat实例的format()方法时,可以提供真正的参数来填充参数索引处的信息。举个例子来说,可以如下格式化文字信息:
String message = "Hello! {0} ! This is your first {1}!"; Object[] params = new Object[]{"caterpillar","Java"}; MessageFormat formatter = new MessageFormat(message); //显示格式化后的信息 System.out.println(formatter.format(params));
MessageFormat实例的format()方法会使用params数组中对象的toString()方法,将取得的String信息依索引位置分别填入{0}到{9}的对应位置,执行format()方法后返回的就是格式化后的信息内容。就上面的程序片段而言,会显示Hello!caterpillar!This is your first Java!信息。
依照这样的方法,如果想在信息绑定时也能进行信息的格式化,让一些信息在程序运行过程中动态决定,则可以在.properties中如下编写,例如编写message2.properties文件如下:
onlyfun.caterpillar.greeting = Hello!{0}! This is your first {1}!
接着可以绑定message2.properties,并在程序中进行信息的格式化,如下范例所示:
package ysu.hxy; import java.util.ResourceBundle; import java.text.MessageFormat; public class MessageFormatDemo { public static void main(String[] args) { try { //绑定messages.properties ResourceBundle resource = ResourceBundle.getBundle("message2"); String message = resource.getString("onlyfun.caterpillar.greeting"); Object[] params = new Object[]{args[0],args[1]}; MessageFormat formatter = new MessageFormat(message); //显示格式化后的信息 System.out.println(formatter.format(params)); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("没有指定参数!"); } } }
运行结果之一如下:
D:\Java_Test>java ysu.hxy.MessageFormatDemo hxy java
Hello!hxy! This is your first java!
4. 国际化信息
Internationalization简称I18N.意思为国际化。为了在应用程序中表示一个区域,Java提供有java.util.Locale类,一个Locale实例包括了语系信息与区域信息。例如en表示英文语系的国家,这个字母组合是在ISO369中定义的,而区域信息则是像US表示美国,这个字母组合则是在ISO 3166中定义的。可以如下这么新增一个Locale的实例,用以表示中文语系zh、中国cn:
Locale locale = new Locale("zh","CN");
当使用ResourceBundle.getBundle()方法时,默认就会自动取得计算机上的语系与区域信息,而事实上信息文件的名称由basename加上语系与地区来组成。例如:
没有指定语言与地区的basename是默认的资源文件名称,当没有提供专用的语系、区域信息文件时,就会寻找默认的资源文件。
如果想要提供中文的信息,由于信息资源文件必须是ISO-8859-1编码,所以对于非西方语系的处理必须先将之转换为Java Unicode Escape格式。例如可以先在message3_zh_CN.txt中编写以下的内容:
ysu.hxy.welcome=您好
ysu.hxy.name=世界
然后使用JDK的工具程序native2ascii来转换。例如:
native2ascii -encoding GB2312 messages3_zh_cn.txt messages_zh_cn.properties
转换后message3_zh_cn.properties文件内容会如下:
ysu.hxy.welcome=\u60a8\u597d
ysu.hxy.name=\u4e16\u754c
将此文件放在classpath可以存取到的路径位置,还可以提供一个默认的信息文件message3.properties:
ysu.hxy.welcome=Hello
ysu.hxy.name=World
利用下面的程序测试一下信息文件。所使用的操作系统为语系设定为中文,区域设定是中国。
package ysu.hxy; import java.util.ResourceBundle; public class I18NDemo { public static void main(String[] args) { ResourceBundle resource = ResourceBundle.getBundle("messages3"); System.out.print(resource.getString("ysu.hxy.welcome")+"!"); System.out.print(resource.getString("ysu.hxy.name")+"!"); } }
根据操作系统的设定,执行程序时会使用默认的语系zh与区域设定中国,所以就会寻找message3_zh_cn.properties的内容。 运行结果:
D:\Java_Test>java ysu.hxy.I18NDemo
您好!世界!
在使用ResourceBundle.getBundle()时可以给定Locale实例作为参数。例如若想提供messages_en_US.properties文件,并想要ResourceBundle.getBundle()取得这个文件的内容,则可以像下面这样编写:
Locale locale = new Locale("en","US"); ResourceBundle resource = ResourceBundle.getBundle("messages",locale);
根据Locale对象的设定,这个程序片段将会取得messages_en_US.properties文件的信息内容。