• java.text.MessageFormat 专题


    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 <code>characterIterators</code> is
         * non-null, AttributedCharacterIterator will be created from the
         * subformats as necessary. If <code>characterIterators</code> is null
         * and <code>fp</code> is non-null and identifies
         * <code>Field.MESSAGE_ARGUMENT</code>, the location of
         * the first replaced argument will be set in it.
         *
         * @exception IllegalArgumentException if an argument in the
         *            <code>arguments</code> 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<AttributedCharacterIterator> 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("<tr bgcolor='#cef'><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td></tr>", 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:geoCode
    longitude:geoCode,latitude:result, body:2.0,reGeoCode:1.0
    longitude: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.<init>(MessageFormat.java:362)
            at java.text.MessageFormat.format(MessageFormat.java:840)



     

  • 相关阅读:
    如何有效的写算法题的几个小tips
    题目
    记录加入博客园,申请开通cnblog
    关于套接字socket程序参数设置
    int main (int argc, const char * argv[0])及指针数组与数组指针
    sleep函数
    signal函数
    C htonl()函数
    位域unsigned char a:4
    关于TCP和UDP的一个理解
  • 原文地址:https://www.cnblogs.com/softidea/p/5530834.html
Copyright © 2020-2023  润新知