Java核心技术卷II(第8版) – 读书笔记 – 第5章

本章的内容是:国际化!

1、Java默认的UTF-8编码为国际化提供了可能。国际化不止是编码、文本,还包括日期、货币等方面。

2、Locale类表示一个地区(的国际化情况),它包括:一种语言、一个位置和一个变量。

如美国:language=English, location=United States

如果只指定了语言,有时候将无法处理货币、时间等。因为语言可能被多个公家共用,但各地的时间、货币表示符号又不同。

3、Java对于语言使用ISO标准的ISO-639-1,每个国家使用2字母的代号表示,想了解的猛击这里。注意中国是zh不是cn哦~

Java对于国家,使用ISO-3166-1,每个国家一般也是两个字母,但多数为大写,猛击这里,例如中国是CN。

4、java.util.Locale有两个参数的构造函数:

 Locale(String language, String country)

很明显第一个要写语言,如zh,第二个是国家,如CN

5、为了方便,Java预定义了上述Locale对象的常量:
如Locale.CHINA
Locale.US等,这些都是语言+位置(国家)。

也定义了只有语言没有位置的,如Locale.CHINESE,但这个不常用。

6、对于本机支持的所有Locale,可以列出:

import java.util.Locale;
public class TestLocale {
	public static void main(String [] args) {
		Locale [] ls = Locale.getAvailableLocales();
		for(Locale l:ls) {
			System.out.println(l.getLanguage()+" "+l.getCountry());
		}
	}
}

我得机器结果如下:

ja JP
es PE
en
ja JP
es PA
sr BA
mk
es GT
ar AE
no NO
sq AL
bg
ar IQ
ar YE
hu
pt PT
el CY
ar QA
mk MK
sv
de CH
en US
fi FI
is
cs
en MT
sl SI
sk SK
it
tr TR
zh
th
ar SA
no
en GB
sr CS
lt
ro
en NZ
no NO
lt LT
es NI
nl
ga IE
fr BE
es ES
ar LB
ko
fr CA
et EE
ar KW
sr RS
es US
es MX
ar SD
in ID
ru
lv
es UY
lv LV
iw
pt BR
ar SY
hr
et
es DO
fr CH
hi IN
es VE
ar BH
en PH
ar TN
fi
de AT
es
nl NL
es EC
zh TW
ar JO
be
is IS
es CO
es CR
es CL
ar EG
en ZA
th TH
el GR
it IT
ca
hu HU
fr
en IE
uk UA
pl PL
fr LU
nl BE
en IN
ca ES
ar MA
es BO
en AU
sr
zh SG
pt
uk
es SV
ru RU
ko KR
vi
ar DZ
vi VN
sr ME
sq
ar LY
ar
zh CN
be BY
zh HK
ja
iw IL
bg BG
in
mt MT
es PY
sl
fr FR
cs CZ
it CH
ro RO
es PR
en CA
de DE
ga
de LU
de
es AR
sk
ms MY
hr HR
en SG
da
mt
pl
ar OM
tr
th TH
el
ms
sv SE
da DK
es HN

7、Locale的各种Get方法就不赘述了,自己查JavaDoc吧。

8、单纯的Locale只是一个标示,而表现层(同样的数字,格式化为不同地区的货币),则是通过Fomartter完成的。

例如:java.text.NumberFormat提供了数字的解析和格式化。

格式化步骤:
(1)getXXXInstance()
(2)format完成从int/double到对应string的过程,如下:

import java.text.NumberFormat;
import java.util.Locale;

public class TestNumFormat {
	public static void main(String [] args) {
		// Default formart
		NumberFormat fmt = NumberFormat.getInstance(Locale.CHINA);
		System.out.println(fmt.format(8888888.33333)); //8,888,888.333

		// Currency format
		NumberFormat fmt2 = NumberFormat.getCurrencyInstance(Locale.CHINA);
		System.out.println(fmt2.format(88.33)); // ¥88.33

		// Integer format
		NumberFormat fmt3 = NumberFormat.getIntegerInstance(Locale.CHINA);
		System.out.println(fmt3.format(8888888.3333)); // 8,888,888
	}
}

9、 解析步骤:

例如从String中抽出人民币多少元:

try {
    // Get format
    NumberFormat fmt4 = NumberFormat.getCurrencyInstance(Locale.CHINA);
    // Parse
    Number num = fmt4.parse("¥88.33");
    System.out.println(num.doubleValue()); // 88.33
    } catch(Exception e){ 
    e.printStackTrace();
}

10、NumberFormat可以通过set/getMax/MinIntegerDigit等设置最多多少位小数。

11、如上,NumberFormat.getCurrencyInstance()用于获取货币格式刷。

NumberFormat.getCurrency()返回货币符号,例如人民币的¥。

12、日期格式化是另外一个重头戏,通过java.text.DateFormat完成。

步骤也是类似的,先getXXXInstance(),然后format,不过参数是java.util.Date。

注意instance多了一个参数style,短、中、长。

DateFormat getDateInstance(int style, Locale aLocale)

例子如下:

import java.text.DateFormat;
import java.util.*;

public class TestDateFormat {
    public static void main(String [] args) {
        // Now
        Date now = new Date();
        // Dateformart
        DateFormat fmt = DateFormat.getDateInstance(DateFormat.LONG, Locale.CHINA);
        System.out.println(fmt.format(now)); // 2012年3月21日

        // DateTimeformart
        DateFormat fmt2 = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.CHINA);
        System.out.println(fmt2.format(now)); // 2012年3月21日 下午09时47分42秒
    }   
}

13、其实更多的时候,我们想要自己控制日期输出,比如2012-03-01 13:33:33这种,这有两种方法,一是之前提到的format大法(见《Java格式化日期字符串》),另外就是通过SimpleDateFormat完成:

import java.text.SimpleDateFormat;
import java.util.*;

class TestSimpleDateFormat {
    public static void main(String [] args) {
        // Now
        Date now = new Date();
        // Make date format 
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
        System.out.println(fmt.format(now)); // 2012-03-21 22:01:04.124
    }   
}

14、其实排序中也隐藏这国际化的风险,因为Java默认是用unicode排序的,这样很多顺序是错误的。。例如中文,我们习惯首字母拼音排序,而Java确实按照code的先后。。

这种排序需要java.util.Collator完成,同样也是用Locale获得当地的Collator,然后将它应用于sort时候就可以了~

下面的第二部分,就是按照首字母排序啦!

import java.text.Collator;
import java.util.*;

class TestCollator {
    public static void main(String [] args) {
        // Get Collator 
        Collator coll = Collator.getInstance(Locale.CHINA);
        // Sort
        ArrayList<String> names = new ArrayList<String>();
        names.add("计算所");
        names.add("中科院");
        names.add("米国");
        // Default sort (按照Unicode编码排序)
        Collections.sort(names);
        for(String name: names) {
            System.out.println(name);
        }   
        // Sort 1 (首字母排序!!)
        System.out.println();
        Collections.sort(names, coll);
        for(String name: names) {
            System.out.println(name);
        }   
    }   
}

15、还可以设置“排序强度”,多语种时候比较有用,需要时候再了解吧。。

16、java.text.MessageFormat用于格式化文本。

它支持占位符,例如:"My name is {2}, work at {0}, my number is {1}",然后后面可以用3个变量替代:

        // MessageFormat
        String msg = MessageFormat.format("My name is {2}, work at {0}, my number is {1}", "ICT", "Coder4", 100);
        System.out.println(msg); // My name is 100, work at ICT, my number is Coder4

这个{}的格式是{idx, type, stype}。

idx就是下标。

type可以是number、time、date、choice。

如果number,则style可以是integer、currency、percent。如果time

如果time/date,style可以是short、medium、long、full或者模板yyyy-MM-dd等。

choice这种是用于a变成an这种小的根据实际语言的改变。

        String msg = MessageFormat.format("My name is {2}, now is {0, date, full}, my number is {1} ", new Date(), "Coder4", 100);
        System.out.println(msg); // My name is 100, now is 2012年3月21日 星期三, my number is Coder4

17、Java内部是UTF-8编码,但系统不一定是,文件更不一定是。

用其他编码打开文件:

out  = new FileWriter(filename, "iso-8859-1");

 注意:文件编码名和Locale中定义的没有关联!!

18、.java文件的编码建议用ascii或者utf-8,如果有特殊字符,可以用naitive2ascii工具搞定。

19、本地化应用时,可能需要翻译大量的UI,此时我们可以用资源包搞定!

一个项目可以对应若干资源包

资源包命名为:

包名_语言_地区。例如:

Msg_de_DE

Msg_zh_CN

20、加载包:

ResourceBundle res =ResourceBuilde.getBundel("Msg", Locale.CHINA);

第一个参数是包名,第二个是Locale

它将先尝试匹配语言、国家和变量。如果失败,放弃语言,根据国家查找,如果都失败就用默认的locale了。

21、对字符串进行包国际化很简单:

MyMsg_zh_CN.properties:

注意这些字符串文件必须是ascii编码的,如果你要中文需要用naive2ascii编译!

下面是一个编译好的例子:

Button = \u6309\u6211

需要加载字符串的时候:

ResourceBundle bundle = ResourceBundle.getBundle("Msg", Locale.CHINA);
String btn_str = bundle.getString("Button"); // 按我

22、如果对字符串之外的资源包,就需要扩展类了:

拓展ListResourceBundle

或者拓展ResourceBundle但是需要实现getKeys()和handleObject(String key)方法。

本章完毕。

 

One thought on “Java核心技术卷II(第8版) – 读书笔记 – 第5章

Leave a Reply

Your email address will not be published. Required fields are marked *