Java常用类库——国际化程序(Locale,ResourceBundle以及MessageFormat处理动态文本)

本章目标

掌握国际化程序的基本实现原理。

掌握资源文件的作用。

掌握Locale类的基本实现原理。

掌握ResourceBundle类的作用。

可以使用MessageFormat处理动态文本。

了解资源类的使用。

国际化程序

国际化的操作就是指一个程序可以同时适应多门语言,即:如果现在程序的使用者是中国人,则会以中文为显示文字,如果现在程序的使用者是英国人,则会以英语为显示文字,也就是说可以通过国际化操作,让一个程序适应各个国家的语言要求。

那么对于各个国家来说,每一个程序的代码是不会有任何改变的,但是只是其显示的文字上有所差异而已。

国际化程序的实现思路:

程序根据不同的语言环境找到不同的资源文件,之后从资源文件中取出内容,资源文件中的内容都是以key—value的形式保存的,所以在读取的时候通过其key找到对应的value即可。

国际化实现的支持类

如果想实现Java程序的国际化操作必须通过以下三个类完成:

java.util.Locale:用于表示一个国家的语言类。

java.util.ResourceBundle:用于访问资源文件。

java.util.MessageFormat:格式化资源文件的占位字符串。

Locale类

Locale表示的是本地,实际上使用的是一个ISO编码的封装类。对于各个国家来说都存在一个唯一的编码,那么这种编码就称为ISO编码,使用Locale可以指定一个具体的国家编码。

例如:

中国的编码:zh-CN

英语-美国的编码:en-US

法语的编码:fr-FR

ResourceBundle

此类是专门完成属性文件读取操作的,读取的时候直接指定文件名即可(此文件名一般不需要指定后缀,后缀统一为*.properties),可以根据Locale所指定的区域码来自动选择所需要的资源文件。

public static final ResourceBundle getBundle(String baseName),此方法是指定操作的资源文件,此方法找到的是默认的操作系统的语言Locale对象。

public static final ResourceBundle getBundle(String baseName, Locale locale),此方法也是指定操作的资源文件,并传入Locale对象。

public final String getString(String key)根据key取得对应的value。

下面通过一道程序来观察资源文件的使用,以及如何使用ResourceBundle读取资源文件。

资源文件命名的时候最好采用单词首字母大写的方式完成。

Message.properties:

info=111HELLO

其中info是程序中需要的内容,而HELLO是此info所指向的具体内容。

从资源文件中读取数据:

import java.util.ResourceBundle ;
public class InterDemo01{
	public static void main(String args[]){
		ResourceBundle rb = ResourceBundle.getBundle("Message") ;	// 找到资源文件,不用编写后缀
		System.out.println("内容:" + rb.getString("info")) ;		// 从资源文件中取得内容
	}
};

Java国际化程序的实现

了解了ResourceBundle类和资源文件之后,下面就结合Locale类一起完成国际化程序的开发。

开发要求:

可以根据不同的国家输出不同国家的"你好"

中文:你好!

英文:Hello!

法语:Bonjour!

分别定义不同的资源文件,此时需要定义三个资源文件,同时在定义资源文件的时候指定好次资源文件对应的语言编码:

中文:Message_zh_CN.properties

英文:Message_en_US.properties

法文:Message_fr_FR.properties

Message_zh_CN.properties内容如下:

info =\u4F60\u597D\uFF01

Message_fr_FR.properties内容如下:

info =Bonjour\!

Message_en_US.properties内容如下:

info =Hello\!

下面就要根据Locale所指定区域的ISO不同,得到不同的资源文件的内容。

import java.util.ResourceBundle ;
import java.util.Locale ;
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") ;		// 表示法国地区
		// 找到中文的属性文件,需要指定中文的Locale对象
		ResourceBundle zhrb = ResourceBundle.getBundle("Message",zhLoc) ;
		// 找到英文的属性文件,需要指定英文的Locale对象
		ResourceBundle enrb = ResourceBundle.getBundle("Message",enLoc) ;
		// 找到法文的属性文件,需要指定法文的Locale对象
		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")) ;
	}
};

以上信息的确读取出来了,但是在程序开发中有一点需要特别注意,对于中文的资源文件,虽然可以直接通过中文读取,但是这样做是不合理的,应该将其进行Unicode编码,转换为Java认识的16进制,此工具为JDK自行提供。

在DOS命令下打开 native2ascii.exe ,然后输入中文回车,就会显示转码后的字符,如下所示:

切记:只要是中文,就必须进行转码操作。

处理动态文本

之前的资源文件中的所有内容实际上都是固定的,而如果现在有些内容,你好,XXX。那么此时就必须在资源文件中进行一些动态文本设置,设置占位符,这些符号的内容暂时不确定,而是在程序执行的时候由程序进行设置的,而要想实现这样的功能,则必须使用MessageForm类。此类是在java.text包中定义的。

在Format类中还存在数字格式化的Format(NumberFormat)、日期格式化的Format(DateFormat)。

占位符使用{数字} 的形式表示,如果现在表示第一个内容“{0}”、第二个内容“{1}” 以此类推。

在MessageFormat类中主要使用format()方法,此方法定义如下:

public static String format(String pattern, Object ... arguments);

使用

文本资源大致如下:

代码如下:

import java.util.ResourceBundle ;
import java.util.Locale ;
import java.text.* ;
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") ;		// 表示法国地区
		// 找到中文的属性文件,需要指定中文的Locale对象
		ResourceBundle zhrb = ResourceBundle.getBundle("Message",zhLoc) ;
		// 找到英文的属性文件,需要指定英文的Locale对象
		ResourceBundle enrb = ResourceBundle.getBundle("Message",enLoc) ;
		// 找到法文的属性文件,需要指定法文的Locale对象
		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,"liuxun")) ;
		System.out.println("法语:" + MessageFormat.format(str3,"liuxun")) ;
	}
};

另外可以设置多个占位符,处理文本。

JAVA新特性——可变参数

在JDK1.5之后JAVA增加了新特性的操作,可以向方法中传递可变参数,以前定义的方法实际上里面的参数都是固定个数的,那么在JDK1.5之后为了解决操作的麻烦,增加了此特性。

测试参数传递:

public class InterDemo04{
	public static void main(String args[]){
		System.out.print("第一次运行:") ;
		fun("LIUXUN","LiU","刘勋") ;	// 传入三个参数
		System.out.print("\n第二次运行:") ;
		fun("HHXY") ;				// 传入一个参数
	}
	public static void fun(Object...args){	// 固定语法,输入任意多个数据,使用数组表示
		for(int i=0;i<args.length;i++){
			System.out.print(args[i] + "、") ;
		}
	}
};

如果觉得以上操作不能明确表示出来的话,也可以直接传递一个数组过去。

public class InterDemo05{
	public static void main(String args[]){
		System.out.print("第一次运行:") ;
		Object[] arg1 = {"LIUXUN","LiU","刘勋"} ;
		fun(arg1) ;	// 传入三个参数
		System.out.print("\n第二次运行:") ;
		Object[] arg2 = {"HHXY"} ;
		fun(arg2) ;				// 传入一个参数
		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] + "、") ;
		}
	}
};

使用一个类代替资源文件

以上的应用已经是国际化的实际操作效果。

所有的要显示的内容实际上都应该放在资源文件之中,但是在JAVA中为了照顾部分习惯使用类的用户,所以也可以直接使用一个类来存放所有的资源文件的内容,但是,此类在操作的时候就必须有一个明显的注意点,必须继承ListResourceBundle。

下面以中文的信息显示:

资源类Message_zh_CN.java

import java.util.ListResourceBundle ;
public class Message_zh_CN extends ListResourceBundle{
	private final Object data[][] = {
		{"info","中文,你好,{0}!"},
		{"info2","中文,毕业院校: {0}!"}
	} ;
	public Object[][] getContents(){	// 覆写的方法
		return data ;
	}
};

注意:资源类继承ListResourceBundle类必须覆写 public Object[][] getContents() 方法

运行主方法:

import java.util.ResourceBundle ;
import java.util.Locale ;
import java.text.* ;
public class InterDemo06{
	public static void main(String args[]){
		Locale zhLoc = new Locale("zh","CN") ;		// 表示中国地区
		// 找到中文的属性文件,需要指定中文的Locale对象
		ResourceBundle zhrb = ResourceBundle.getBundle("Message",zhLoc) ;
		String str1 = zhrb.getString("info") ;
		String str2 = zhrb.getString("info2") ;
		System.out.println("中文:" + MessageFormat.format(str1,"刘勋")) ;
		System.out.println("中文:" + MessageFormat.format(str2,"黄淮学院")) ;
	}
};

需要注意的是:占位符的下标{0}、{1}、、、是按照其中一个键的顺序设置的。

不管是资源类还是资源文件,找到的时候都是Message,那么如果现在多种资源文件一起出来,那么最终找到的是哪一个呢?

实际上此时就需要区分优先级:

资源类的优先级大于资源文件的优先级,其次是文件名带区域标识的大于不带标识的。

Message_zh_CN.class > Message_zh_CN.properties > Message.properties

总结:

国际化程序的实现思路:程序与显示相分离,根据不同的Locale指定的区域找到不同的资源文件并根据key取得对应的value。

当然,在实际的开发中,包括以后要学习的struts,都经常使用资源文件的方式保存所有的信息内容,其基本原理是依靠了ResourceBundle类取得资源文件中的内容。

MessageFormat 是Format的子类。

时间: 2024-08-04 03:51:31

Java常用类库——国际化程序(Locale,ResourceBundle以及MessageFormat处理动态文本)的相关文章

Java常用排序算法+程序员必须掌握的8大排序算法+二分法查找法

Java 常用排序算法/程序员必须掌握的 8大排序算法 本文由网络资料整理转载而来,如有问题,欢迎指正! 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排序(直接选择排序.堆排序) 4)归并排序 5)分配排序(基数排序) 所需辅助空间最多:归并排序 所需辅助空间最少:堆排序 平均速度最快:快速排序 不稳定:快速排序,希尔排序,堆排序. 先来看看 8种排序之间的关系: 1.直接插入排序 (1)基本思想:在要排序的一组数中,假设前面(n-1)[n>=2]

Google的Java常用类库 Guava资料

java的人应该都知道Apache commons的java常用类库吧,这个Guava和commons一样,封装出一套比jdk本身提供的常用类库强大.既然有了这个这么强大的类库,我们就没必要重复造轮子了.这东西怎么用,看看官网的文档和API.英文不好的,也有网上翻译出来共享的.开始Guava之旅猛击下面的链接 官方地址:http://code.google.com/p/guava-libraries/  [大家都知道这个要FQ哦,windows下推荐ziyoumen软件] 官方翻译文档:http

Google的Java常用类库 Guava

Guava 中文是石榴的意思,该项目是 Google 的一个开源项目,包含许多 Google 核心的 Java 常用库. 1. 基本工具 [Basic utilities] 让使用Java语言变得更舒适 1.1 使用和避免null:null是模棱两可的,会引起令人困惑的错误,有些时候它让人很不舒服.很多Guava工具类用快速失败拒绝null值,而不是盲目地接受 1.2 前置条件: 让方法中的条件检查更简单 1.3 常见Object方法: 简化Object方法实现,如hashCode()和toSt

Java常用类库之StringBuilder与StringBuffer

String与StringBuffer与StringBuilder的比较 String的内容一旦声明则不可改变,如果改变,则改变的肯定是String的引用地址. StringBuffer则是有个字符缓冲区,所有的操作都是对字符缓冲区中操作.与StringBuilder类似. 1. 在执行速度方面的比较:StringBuilder > StringBuffer 2. StringBuffer与StringBuilder,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一

Java 常用排序算法/程序员必须掌握的 8大排序算法

Java 常用排序算法/程序员必须掌握的 8大排序算法 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排序(直接选择排序.堆排序) 4)归并排序 5)分配排序(基数排序) 所需辅助空间最多:归并排序 所需辅助空间最少:堆排序 平均速度最快:快速排序 不稳定:快速排序,希尔排序,堆排序. 先来看看 8种排序之间的关系: 1.直接插入排序 (1)基本思想:在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排 好顺序的,现在要把第n 个数插到前

Java学习之国际化程序

国际化程序就是把程序的语言根据用户使用的语言显示,各个国家的用户都可以看懂 实现方法就是把输出文字都写在配置文件里,然后根据用户系统语言选择不同的语言输出 1 package com.gh; 2 3 import java.text.MessageFormat; 4 import java.util.Locale; 5 import java.util.ResourceBundle; 6 import java.util.Scanner; 7 /** 8 * 国际化程序 9 * 用配置文件改变输

java常用类库

1.StringBuffer StringBuffer是使用缓冲区的,本身也是操作字符串的,但与String不同,String类的内容一旦声明之后则不可改变,改变的只是其内存地址的指向,而StringBuffer中的内容可以改变. 对StringBuffer而言,本身是一个具体的操作类,所以不能像String那样采用直接赋值的方式进行对象的实例化,必须通过构造方法完成. StringBuffer类的应用:频繁修改字符串的内容,用String类是不合适的,此时应该用StringBuffer. 2.

JAVA常用类库简介(转)

Java编程语言中为方便学习者学习,编制了许多类,这些类已经经过测试,都是我们编程的基础.如果不利用这些已存在的类,我们的编程工作将变得异常复杂并且效率低下.所以我们应尽可能多的掌握Java基本类库的内容.类库中的类按照其用途归属于不同的包中. 1.java.lang包 java.lang包 是Java中最常用的包,程序不需要注入,就可以使用该包中的类,利用包中的类可以设计最基本的Java程序. 2.java.awt包 java.awt包中的类提供了图形界面的创建方法,包括按钮.文本框.列表框.

Java常用类库之时间操作类——Date、Calendar、DateFormat、SimpleDateFormat及实例操作

学习目标 掌握Date类的使用 可以使用Calendar类取得一个完整的日期 掌握日期格式化的操作 可以使用SimpleDateFormat进行日期的格式化转换操作 编写取得日期的操作类 进一步掌握Calendar类的使用 进一步掌握SimpleDateFormat类的使用 Date类是一个较为常用的类,但是其操作的日期格式会有一些不符合个人要求,而如果想要进一步取得一些自己需要的时间,则可以使用Calendar类. Date类 在java.util包中定义了Date类,Date类本身使用非常简