博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
格式化消息
阅读量:4049 次
发布时间:2019-05-25

本文共 6876 字,大约阅读时间需要 22 分钟。

-- Start

任何程序都需要向用户显示消息, 无论是成功的消息或者是失败的消息. 通常我们通过字符串拼接来构造消息, 下面是一个简单的例子.

public static void main(String[] args) throws Exception {	Scanner in = new Scanner(System.in);	System.out.print("What is your name? ");	String name = in.nextLine();	System.out.print("What's your birthday? ");	Date birthday = DateFormat.getDateInstance().parse(in.nextLine());	int age = getAge(birthday);	// 通过字符串拼接构造消息	System.out.println("Welcome " + name + ", your birthday is " + birthday + " and you are " + age + " years old.");}public static int getAge(Date birthday) {	Calendar now = Calendar.getInstance();	Calendar birthdayCal = Calendar.getInstance();	birthdayCal.setTime(birthday);	return now.get(Calendar.YEAR) - birthdayCal.get(Calendar.YEAR);}
如果我们只面向一个国家或地区的用户, 上面的做法是可以的. 但是有好多大公司, 它们在全球各个国家和地区都有分公司, 这就要求我们的根据不同的语言环境来显示消息. MessageFormat 类提供的方法可以使我们很容易构造消息. ResourceBundle 存储了国际化的消息, 下面是一个简单的例子.

public static void main(String[] args) throws Exception {	displayMessage(Locale.CHINA);	System.out.println();	displayMessage(Locale.US);}private static void displayMessage(Locale currentLocale) throws Exception {	ResourceBundle messages = ResourceBundle.getBundle("MessageBundle", currentLocale);	Scanner in = new Scanner(System.in);	System.out.print(messages.getString("nameInfo"));	String name = in.nextLine();	System.out.print(messages.getString("birthdayInfo"));	Date birthday = DateFormat.getDateInstance(DateFormat.DEFAULT, currentLocale).parse(in.nextLine());	int age = getAge(birthday);	MessageFormat formatter = new MessageFormat("");	formatter.setLocale(currentLocale);	formatter.applyPattern(messages.getString("helloMsg"));	System.out.println(formatter.format(new Object[] { name, birthday, age }));}private static int getAge(Date birthday) {	Calendar now = Calendar.getInstance();	Calendar birthdayCal = Calendar.getInstance();	birthdayCal.setTime(birthday);	return now.get(Calendar.YEAR) - birthdayCal.get(Calendar.YEAR);}
MessageBundle_en_US.properties

nameInfo = What is your name? birthdayInfo = What's your birthday? helloMsg = Welcome {0}, your birthday is {1,date,medium} and you are {2,number,integer} years old.
MessageBundle_zh_CN.properties

#你叫什么名字? nameInfo = \u4f60\u53eb\u4ec0\u4e48\u540d\u5b57\u003f\u0020#你的出生年月日是? birthdayInfo = \u4f60\u7684\u51fa\u751f\u5e74\u6708\u65e5\u662f\u003f\u0020#欢迎 你{0}, 你的生日是{1,date,medium}, 你今年 {2,number,integer} 岁了.helloMsg = \u6b22\u8fce\u0020\u4f60{0}, \u4f60\u7684\u751f\u65e5\u662f{1,date,medium}, \u4f60\u4eca\u5e74 {2,number,integer} \u5c81\u4e86.
正如上面我们看到的那样, 我们需要把 Resouce 中的中文转换成 Unicode 编码, 下面的小程序可以帮助我们完成这样的工作, 或者你也可以使用 Java 安装目录下的 
native2ascii 命令来完成同样的任务.

public static void main(String[] args) throws Exception {	String s = "你叫什么名字? ";	for (char c : s.toCharArray()) {	    String codePoint = "0000" + Integer.toHexString(c);	    System.out.print("\\u" + codePoint.substring(codePoint.length() - 4));	}}
上面例子的运行结果如下:

你叫什么名字? Shang Bo你的出生年月日是? 2000-01-01欢迎 你Shang Bo, 你的生日是2000-1-1, 你今年 12 岁了.What is your name? ScottWhat's your birthday? January 1, 2000Welcome Scott, your birthday is Jan 1, 2000 and you are 12 years old.
通常我们要向消息中插入 日期, 时间, 字符串, 数字, 货币和百分比等类型的变量. 在消息中, 需要插入的变量处于大括号中, 可以有如下形式:

// 形式{ ArgumentIndex }{ ArgumentIndex , FormatType }{ ArgumentIndex , FormatType , FormatStyle }// 例子Welcome {0}, your birthday is {1,date,medium} and you are {2,number,integer} years old.formatter.format(new Object[] { name, birthday, age })// 说明ArgumentIndex 指的是 format 方法中 Object 对象数组中的索引.FormatType 指的是数据类型, 可以是 number, date, time, choice 之一.FormatStyle 指的是格式化样式, 可以是 short, medium, long, full, integer, currency, percent 或 自定义格式.

下面的表格总结了 FormatType 和 FormatStyle 和 Format 类的对应关系.

Format Type  Format Style  Subformat Created
(none)  (none)  null
number  (none)  NumberFormat.getInstance(getLocale())
  integer  NumberFormat.getIntegerInstance(getLocale())
  currency  NumberFormat.getCurrencyInstance(getLocale())
  percent  NumberFormat.getPercentInstance(getLocale())
  SubformatPattern  new DecimalFormat(subformatPattern, DecimalFormatSymbols.getInstance(getLocale()))
date  (none)  DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())
  short  DateFormat.getDateInstance(DateFormat.SHORT, getLocale())
  medium  DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())
  long  DateFormat.getDateInstance(DateFormat.LONG, getLocale())
  full  DateFormat.getDateInstance(DateFormat.FULL, getLocale())
  SubformatPattern  new SimpleDateFormat(subformatPattern, getLocale())
time  (none)  DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())
  short  DateFormat.getTimeInstance(DateFormat.SHORT, getLocale())
  medium  DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())
  long  DateFormat.getTimeInstance(DateFormat.LONG, getLocale())
  full  DateFormat.getTimeInstance(DateFormat.FULL, getLocale())
  SubformatPattern  new SimpleDateFormat(subformatPattern, getLocale())
choice  SubformatPattern  new ChoiceFormat(subformatPattern)

有时候看上去非常简单的消息, 构造起来却非常困难, 如: 我想构造如下消息.

这有n个人
如果n是0的话, 我们不能说 "这有0个人", 只能说 "这没有人", 英语更复杂.

there is no poeple.there is one person.there are n poeple.
如何构造这样的消息呢? 使用 ChoiceFormat 类可以很容易解决这个问题.

public static void main(String[] args) throws Exception {	displayMessage(Locale.CHINA);	System.out.println();	displayMessage(Locale.US);}private static void displayMessage(Locale currentLocale) throws Exception {	ResourceBundle messages = ResourceBundle.getBundle("MessageBundle", currentLocale);		double[] limits = {0, 1, 2}; 	String[] formats = {messages.getString("no"), messages.getString("one"), messages.getString("more")};	ChoiceFormat choiceForm = new ChoiceFormat(limits, formats);	MessageFormat formatter = new MessageFormat("");	formatter.setLocale(currentLocale);	formatter.applyPattern(messages.getString("pattern"));	formatter.setFormats(new Format[] {choiceForm, NumberFormat.getInstance()});	System.out.println(formatter.format(new Object[] {0, 0})); 	System.out.println(formatter.format(new Object[] {1, 1}));	System.out.println(formatter.format(new Object[] {2, 2}));	System.out.println(formatter.format(new Object[] {2, 3}));	System.out.println(formatter.format(new Object[] {2, 4}));	System.out.println(formatter.format(new Object[] {2, 5}));		// 1. 传入的第一个参数是 2	// 2. 到limits数组中查找 2, 找到 2 在数组中的下标是 2	// 3. 到formats数组中查找 下标是 2 的消息, 英语环境是 are {1} people	// 4. 用第二个参数 6 替换 消息中的  {1} 得到 are 6 people	System.out.println(formatter.format(new Object[] {2, 6})); }
MessageBundle_zh_CN.properties

# 这pattern = \u8fd9{0}.# 没有人no = \u6ca1\u6709\u4eba# 有1个人one = \u6709\u0031\u4e2a\u4eba#有{1}个人more = \u6709{1}\u4e2a\u4eba
MessageBundle_en_US.properties

pattern = there {0}.no = is no peopleone = is one personmore = are {1} people
运行结果如下:

这没有人.这有1个人.这有2个人.这有3个人.这有4个人.这有5个人.这有6个人.there is no people.there is one person.there are 2 people.there are 3 people.there are 4 people.there are 5 people.there are 6 people.

---
更多参见:
--
声 明:转载请注明出处
-- Last Updated on 2012-08-05
-- Written by ShangBo on 2012-05-15
-- End
你可能感兴趣的文章
如此调用
查看>>
计算机的发展史
查看>>
带WiringPi库的交叉编译如何处理一
查看>>
带WiringPi库的交叉笔译如何处理二之软链接概念
查看>>
Spring事务的七种传播行为
查看>>
ES写入找不到主节点问题排查
查看>>
Java8 HashMap集合解析
查看>>
欢迎使用CSDN-markdown编辑器
查看>>
Android计算器实现源码分析
查看>>
Android系统构架
查看>>
Android 跨应用程序访问窗口知识点总结
查看>>
各种排序算法的分析及java实现
查看>>
SSH框架总结(框架分析+环境搭建+实例源码下载)
查看>>
自定义 select 下拉框 多选插件
查看>>
js获取url链接携带的参数值
查看>>
gdb 调试core dump
查看>>
gdb debug tips
查看>>
arm linux 生成火焰图
查看>>
linux和windows内存布局验证
查看>>
linux insmod error -1 required key invalid
查看>>