博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java.text.MessageFormat 专题
阅读量:6825 次
发布时间:2019-06-26

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

 

java.text.MessageFormat类

MessageFormat提供一种语言无关的方式来组装消息,它允许你在运行时刻用指定的参数来替换掉消息字符串中的一部分。你可以为MessageFormat定义一个模式,在其中你可以用占位符来表示变化的部分:

import java.text.MessageFormat;import java.util.Date;public class MessageFormatTest {    public static void main(String[] args) {        Object[] arguments = {                7,                new Date(System.currentTimeMillis()),                "a disturbance in the Force"        };        String result = MessageFormat.format(                "At {1,time} on {1,date}, there was {
2} on planet {0,number,integer}.", arguments); System.out.println(result); //output: // At 14:08:27 on 2017-7-7, there was a disturbance in the Force on planet 7. }}

占位符的格式为{ ArgumentIndex , FormatType , FormatStyle },详细说明可以参考MessageFormat的API说明文档。这里我们定义了两个占位符,其中的数字对应于传入的参数数组中的索引,{0}占位符被第一个参数替换,{1}占位符被第二个参数替换,依此类推。

最多可以设置10个占位符,而且每个占位符可以重复出现多次,而且格式可以不同,比如{1,date}和{1,time},{1,number,#.##}。而通过将这些模式定义放到不同的资源文件中,就能够根据不同的locale设置,得到不同的模式定义,并用参数动态替换占位符。
步骤:
1、找出可变的部分,并据此定义模式,将模式放入不同的资源文件中。
2、创建MessageFormat对象,并设置其locale属性。
MessageFormat formatter = new MessageFormat("");
formatter.setLocale(currentLocale);
3、从资源包中得到模式定义,以及设置参数。
messages = ResourceBundle.getBundle(
"i18n.resource.MessagesBundle",currentLocale);
Object[] arguments= {new Long(3), "MyDisk"};;
4、利用模式定义和参数进行格式化。
String result = MessageFormat.format(messages.getString(key), arguments);

http://blog.csdn.net/turkeyzhou/article/details/4487917

注意:

参数为Number类型或Date类型时,会被格式化。数字会转换成科学计数法,譬如 123456,会format成 123,456
java.text.MessageFormat#subformat

/**     * Internal routine used by format. If characterIterators is     * non-null, AttributedCharacterIterator will be created from the     * subformats as necessary. If characterIterators is null     * and fp is non-null and identifies     * Field.MESSAGE_ARGUMENT, the location of     * the first replaced argument will be set in it.     *     * @exception IllegalArgumentException if an argument in the     *            arguments array is not of the type     *            expected by the format element(s) that use it.     */    private StringBuffer subformat(Object[] arguments, StringBuffer result,                                   FieldPosition fp, List
characterIterators) { // note: this implementation assumes a fast substring & index. // if this is not true, would be better to append chars one by one. int lastOffset = 0; int last = result.length(); for (int i = 0; i <= maxOffset; ++i) { result.append(pattern.substring(lastOffset, offsets[i])); lastOffset = offsets[i]; int argumentNumber = argumentNumbers[i]; if (arguments == null || argumentNumber >= arguments.length) { result.append('{').append(argumentNumber).append('}'); continue; } // int argRecursion = ((recursionProtection >> (argumentNumber*2)) & 0x3); if (false) { // if (argRecursion == 3){ // prevent loop!!! result.append('\uFFFD'); } else { Object obj = arguments[argumentNumber]; String arg = null; Format subFormatter = null; if (obj == null) { arg = "null"; } else if (formats[i] != null) { subFormatter = formats[i]; if (subFormatter instanceof ChoiceFormat) { arg = formats[i].format(obj); if (arg.indexOf('{') >= 0) { subFormatter = new MessageFormat(arg, locale); obj = arguments; arg = null; } } } else if (obj instanceof Number) { // format number if can subFormatter = NumberFormat.getInstance(locale); } else if (obj instanceof Date) { // format a Date if can subFormatter = DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.SHORT, locale);//fix } else if (obj instanceof String) { arg = (String) obj; } else { arg = obj.toString(); if (arg == null) arg = "null"; } // At this point we are in two states, either subFormatter // is non-null indicating we should format obj using it, // or arg is non-null and we should use it as the value. if (characterIterators != null) { // If characterIterators is non-null, it indicates we need // to get the CharacterIterator from the child formatter. if (last != result.length()) { characterIterators.add( createAttributedCharacterIterator(result.substring (last))); last = result.length(); } if (subFormatter != null) { AttributedCharacterIterator subIterator = subFormatter.formatToCharacterIterator(obj); append(result, subIterator); if (last != result.length()) { characterIterators.add( createAttributedCharacterIterator( subIterator, Field.ARGUMENT, Integer.valueOf(argumentNumber))); last = result.length(); } arg = null; } if (arg != null && arg.length() > 0) { result.append(arg); characterIterators.add( createAttributedCharacterIterator( arg, Field.ARGUMENT, Integer.valueOf(argumentNumber))); last = result.length(); } } else { if (subFormatter != null) { arg = subFormatter.format(obj); } last = result.length(); result.append(arg); if (i == 0 && fp != null && Field.ARGUMENT.equals( fp.getFieldAttribute())) { fp.setBeginIndex(last); fp.setEndIndex(result.length()); } last = result.length(); } } } result.append(pattern.substring(lastOffset, pattern.length())); if (characterIterators != null && last != result.length()) { characterIterators.add(createAttributedCharacterIterator( result.substring(last))); } return result; }

 

Java里从来少不了字符串拼接的活,Java程序员也肯定用到过StringBuffer,StringBuilder,以及被编译器优化掉的+=。但这些都和下文要谈的无关。

直接使用"+"拼接比较多的字符串,变量一多,可读性就下降,出错的几率就增加,并且难以维护。

需要拼接的变更比较多时,可以使用MessageFormat.format。
示例:

String[] tdArr=...; String result=MessageFormat.format("{0}{1}{2}{3}", tdArr);

 

这段代码将把数组tdArr中的四个元素分别插入到{0},{1},{2},{3}的位置。

你看看,是不是这样形式和内容有效的分开了。容易想象,当元素增多时,这种方式优势很明显。

一件事有很多手段来达成,知道那种手段更好,是你经验的体现和专业化的特征。

 

使用下标来决定拼接的位置,第一个参数的下标为0,pattern中下标的位置是不要求是顺序的

public static void main(String[] args) {        String longitude = "1.0";        String latitude = "2.0";        String result = "result";        String geoCode = "geoCode";        String format1 = MessageFormat.format("longitude:{0},latitude:{1}, body:{2},reGeoCode:{3}", longitude, latitude, result, geoCode);        System.out.println(format1);        String format2 = MessageFormat.format("longitude:{3},latitude:{2}, body:{1},reGeoCode:{0}", longitude, latitude, result, geoCode);        System.out.println(format2);        String format3 = MessageFormat.format("longitude:{2},latitude:{3}, body:{0},reGeoCode:{1}", longitude, latitude, result, geoCode);        System.out.println(format3);    }

输出:

longitude:1.0,latitude:2.0, body:result,reGeoCode:geoCodelongitude:geoCode,latitude:result, body:2.0,reGeoCode:1.0longitude:result,latitude:geoCode, body:1.0,reGeoCode:2.0

 

 

java.text.MessageFormat格式化字符串时的小技巧

public static void main(String[] args) throws InterruptedException {        MessageFormat form = new MessageFormat(                "{2,date,yyyy-MM-dd HH:mm:ss.SSS} The disk \"{1}\" contains {0,number,#.##} file(s).{3}");        int fileCount = 1273273237;        String diskName = "MyDisk";        Object[] testArgs = {
new Long(fileCount), diskName, new Date(),new Date()}; System.out.println(form.format(testArgs)); }

 

执行结果:2016-05-26 13:41:59.162 The disk "MyDisk" contains 1273273237 file(s).16-5-26 下午1:41

 

如果缺少ArgumentIndex 则会报错:

java.lang.IllegalArgumentException: can't parse argument number:         at java.text.MessageFormat.makeFormat(MessageFormat.java:1429)        at java.text.MessageFormat.applyPattern(MessageFormat.java:479)        at java.text.MessageFormat.
(MessageFormat.java:362) at java.text.MessageFormat.format(MessageFormat.java:840)

 

 

 

你可能感兴趣的文章
获取客户端ip地址
查看>>
sessionid如何产生?由谁产生?保存在哪里?
查看>>
oracle 监听服务异常
查看>>
网络流——最大流Dinic算法
查看>>
下面的div浮动上来了
查看>>
程序员生存定律
查看>>
windows 下搭建 apache + php52 + postgreSQL7/8/9环境
查看>>
ECMAscript一(对象种类)
查看>>
python正则表达式
查看>>
分布式系统的面试题3
查看>>
[原译]理解并实现装饰器模式
查看>>
移动端文本框被原生键盘弹出后挡住文本框
查看>>
项目启动会的意义
查看>>
js捕捉浏览器关闭事件
查看>>
1.6 贪婪算法
查看>>
进击的Python【第十章】:Python的高级应用(多进程,进程间通信,协程与异步,牛逼的IO多路复用)...
查看>>
数据类型
查看>>
Linux环境下的SVN创建新的项目
查看>>
CSMA/CD
查看>>
ICMP
查看>>