java国际化——消息格式化+文本文件和字符集

【0】README

1) 本文部分文字描述转自 core java volume 2 , 测试源代码均为原创, 旨在理解 java国际化——消息格式化+文本文件和字符集 的基础知识 ;
2) 由于本文涉及到的源代码都比较简单,所以直接将全部代码po到了本文对应位置,没有提供下载link;


【1】消息格式化

1)java类库中有一个 MessageFormat 类, 用来格式化带变量的文本, 如:

“on {2}, a {0} destroyed {1} houses and caused {3} of damage”;

  • 1.1)括号中的数字是一个占位符, 可以用实际的名字和值来替换它。
  • 1.2)使用静态方法 MessageFormat.format 可以用实际的值来替换这些占位符。从JDK5 开始, 它已经是一个 varargs 方法了,所以你可以通过下面的方法提供参数: (干货——MessageFormat.format 可以用实际的值来替换这些占位符)

    String msg = MessageFormat.format(“on {2}, a {0} destoryed {1} houses and caused {3} of damage”, “hurricane”, 99, new GregorianCalendar(1999,0,1).getTIme(), 10.0E8);

  • 1.3)如何替换: {0}被 hurricane 替换, {1} 被 99 替换, 等;

  • 1.4) 通过为占位符提供可选的格式,就可以做到这一点:

    on {2, date, long}, a {0} destoryed {1} houses and caused {3, number, currency} of damage ;
    替换参数后, on january 1, 1999, a hurricane destoryed 99 houses and caused $1000000 of damage;


2)一般来说,占位符索引后可以跟一个类型和一个风格,它们之间用逗号隔开,类型可以是:number + time + date + choice; (干货——占位符索引后可以跟一个类型和一个风格,注意类型list和风格list都有哪些)
  • 2.1)number 类型:可以是 integer, currency, percent, 或者可以是数字格式模式,就像 $ , ##0;
  • 2.2)如果类型是 time 或 date: 那么风格可以是 short, medium, long, full,或者是一个日期格式模式, 就像 yyyy-MM-dd;

Warning)静态的 MessageFormat.format 方法使用当前的locale 对值进行格式化。要想用任意的 locale 进行格式化, 还有一些工作要做, 因为这个类还没有提供任何可以使用的 varargs 方法, 你需要把将要格式化的值放置在 Object[] 数组中, 就想下面这样:

MessageFormat mf = new MessageFormat(pattern, loc);
String msg = mf.format(new Object[]{values});

3)看个荔枝(测试 选择格式化( 一个下限 + 一个格式字符串)以及不同Locale的formatter 和 format(pattern, Object… args)):

// 测试 选择格式化( 一个下限 + 一个格式字符串)以及不同Locale的formatter
    public static void main2(String[] args)
    {
        String msg = "on {2, date, long}, a {0} destoryed {1} houses and caused {3, number, currency} of damage" ;
        // pattern == msg;
        String newMsg = MessageFormat.format(msg, new Object[]{"hurricane", 99, new GregorianCalendar(1999,0,1).getTime(), 10.0E8});
        System.out.println("locale[China] = " + newMsg); //Locale == 中国

        MessageFormat formatter = new MessageFormat(msg, Locale.US);
        String newMsg_US = formatter.format(new Object[]{"hurricane", 99, new GregorianCalendar(1999,0,1).getTime(), 10.0E8});
        System.out.println("locale[US] = " + newMsg_US);// Locale == US
    }

    // test for format(pattern, Object... args)
    public static void main1()
    {
        String str = "{0} | {1} | {0} | {1} | {2}";
        Object[] array = new Object[] { "A", "B", "C" };
        // format(pattern, Object... args);
        String msg = MessageFormat.format(str, array);
        System.out.println(msg); // A | B | A | B | C
    }

这里写图片描述
这里写图片描述


【2】 消息格式化之选择格式

1)problem+solution

  • 1.1)problem: “on {2}, a {0} destoryed {1} houses and caused {3} of damage. “, 如果用“earthquake” 来替换代表灾难的占位符{0}, 那么在英语中,这句话就不正确了,因为,
    on january 1, 1999, a earthquack destoryed, 因为 earthquake 的首字母是 e, 冠词是an 而不是 a;
  • 1.2)solution:我们希望消息能随占位符发生变化, 这样就能根据具体的值形成

    no houses
    one house
    2 houses

  • 1.3) choice 的格式化选项就是为了这个目的而设计的。 (干货——choice格式化选项)

    • 1.3.1)一个选择格式是由一个序列对构成的, 每一对都包括 : 一个下限 + 一个格式字符串;
    • 1.3.2)下限和格式字符串由一个 # 符号分割, 对与对之间由 符号 | 分割;
      如:{1, choice,0#no houses | 1#one house|2#{1} houses}
      0#no houses : 0 是 下限, # 是分割符, no houses 是格式化字符串;(注意 0, 1, 是下限,最低限度) (干货——选择格式化: 一个下限 + 一个格式字符串)
      1.3.3)下表显示了格式字符串对 {1} 的不同值产生的作用:

2)可以使用 < 符号来表示如果替换值严格小于下限,则选中这个选择项;也可以使用 ≤ (unicode中代码是 u\2264)来实现 和 # 相同 的效果。如果愿意的话,甚至可以将第一个下限值定义为 -∞(unicode 编码是 -\u221E);

例如: -∞ < no houses |0 < one house |2≤{1} houses; 或者使用 Unicode 转移字符: -\u221E < no houses | 0 < one house |2\u2264 {1} houses;

3)看个荔枝( 选择格式(no houses, one house, 3 houses)):

格式化命令为:  String pattern = “on {2, date, long}, {0} destoryed {1, choice, 0#no houses|1#one house|2#{1} houses}” + “and caused {3, number, currency} of damage”;

// 选择格式(no houses, one house, 3 houses)
    // 下限和格式字符串由一个 # 符号分割, 序列对间由 符号 | 分割;
    public static void main3()
    {
        //String msg = "{-\u221E<no houses|0<one house|2\u2264 {0} houses}";
        String msg = "{0, choice, 0#no houses|1#one house|2#{0} houses}";
        System.out.println(MessageFormat.format(msg, new Object[]{-1}));
        System.out.println(MessageFormat.format(msg, new Object[]{0}));
        System.out.println(MessageFormat.format(msg, new Object[]{1}));
        System.out.println(MessageFormat.format(msg, new Object[]{2}));     
    }

这里写图片描述


【3】文本文件和字符集

1) java是完全基于Unicode的,但是 os 一般有它们自己的字符编码,比如在 美国是 ISO-8859-1(8位代码,有时候也称为 ANSI 代码), 在台湾是 Big5;
2) 当把数据保存到一个文本文件中时,应该照顾到本地的字符编码,这样,用户就可以用它们的其他程序打开这个文本文件。

  • 2.1)字符编码是在 FileWriter 的构造器中指定的: out = newFileWriter(filename, “ISO-8859-1”);
  • 2.2)problem:遗憾的是, 目前,locale 和字符编码间没有任何联系。 比如, 你的 用户选择的是台湾的locale_zh_TW, 但是在 java中并没有提供任何方法来告诉你用 Big5 字符编码是最恰当的;

【4】源文件的字符编码

1)作为 coder, 要牢记你需要与java 编译器进行交互: 这种交互需要通过本地系统的工具来完成;
2)看个荔枝:

  • 2.1)使用中文版的记事本来写你的java 源代码文件, 但这样写出来的源代码不能随处使用;因为它们使用的是本地的字符编码;
  • 2.2)只有编译后的class 文件才能随处使用, 因为它们会自动地使用 “modified UTF-8” 编码来处理标识符和字符串。

3)这意味着即使在程序编译和运行时,依然有3种字符编码参与其中:

  • 3.1)源文件: 本地编码;
  • 3.2)类文件: modified UTF-8;
  • 3.3)虚拟机: UTF-16;

Attention)

  • A1) 可以用 -encoding 标记来设定你的源文件的字符编码, 如 , javac -encoding Big5 Myfile.java

4)为了使你的源文件到处都可用, 必须使用普通 的 ASCII 编码: 也就是说, 你需要将所有 非ASCII 字符转换成等价的 Unicode 编码;

  • 4.1)jdk 有一个工具 native2ascii :可以用它来将本地字符编码转换为 普通 的 ASCII , 这个工具直接将输入中的每一个非 ASCII 字符替换为 跟尾儿 \u 加上四位 16进制数字的Unicode值;(干货——native2ascii 工具的作用)
  • 4.2)如何使用 native2ascii 工具:
    native2ascii Myfile.java Myfile.temp
  • 4.3)用 -reverse 进行逆向转换:
    native2ascii -reverse myfile.temp myfily.java
  • 4.4)用 -encoding 选项指定另一种编码:编码的名字必须是 编码表所列出来的名字之一, 如: native2ascii -encoding Big5 myfile.java myfile.temp

5)看个荔枝(关于 native2ascii 工具)

  • 5.1)native2ascii HelloWorld.java HelloWorld.temp
  • 这里写图片描述

  • 5.2)native2ascii -encoding Big5 HelloWorld.java HelloWorldTW.temp

  • 这里写图片描述

  • 5.3)native2ascii -reverse HelloWorld.temp Reverse.java

  • 这里写图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值