针对locale的服务
----------------
在 java.text 和 java.util 包里支持超过100个的 locale。这些locale 可以为世界上大多数地区的人所使用,然而对某些地区的支持仍然未被支持。为了让JAVA支持这些 locale,需要做很多调查工作,比如说研究和确定数字和日期的格式,国家名称的翻译,排列的次序。某些情形下,设置是政治上的冲突都会影响到locale的内容。事实上,JAVA平台上的locale做不到“与时具进”。
有一种解决办法就是提供新的编程接口(API)让编程人员使用任意的 locale 数据。Java SE 6 里提供给编程人员一个新的接口,可让定制的 locale 插到应用程序上或者是关联到服务。幸运的是,当前正在进行的一个项目 Common Locale Data Repository (CLDR通用区域数据仓库)正在努力地跟踪研究现今世界上所有的区域数据并且维护这些数据。Unicode 组织主持这个项目。借助新的“区域相关的服务提供接口”,就可让应用程序
使用任意的与区域相关的数据。
为了使用区域相关的数据和服务,先要确定应用程序需要什么样的功能。可以为以下列出的类应用与区域相关的数据:
* java.text.BreakIterator
* java.text.Collator
* java.text.DateFormat
* java.text.DateFormatSymbols
* java.text.DecimalFormatSymbols
* java.text.NumberFormat
* java.util.Currency
* java.util.Locale
* java.util.TimeZone
确定了需要使用区域相关数据的功能后,就要遵照服务提供接口来实现,这些接口是定义在java.text.spi 和 java.util.spi 包里。
比如说,想要为一个新的区域相关的数据提供 DateFormat 对象,可以通过实现抽象类
java.text.spi.DateFormatProvider里的
* getAvailableLocales
* getDateInstance
* getDateTimeInstance
* getTimeInstance
这些方法达到目的。
注意,getAvailableLocales 方法是继承自父类 LocaleServiceProvider,因此所有的SPI提供者必须实现此方法来声明它们所支持的区域对象。其他三个方法是被映射到相关类上的工厂方法,譬如 getDateInstance 方法就是在 java.text.DateFormat 类上的。
实现了以上的这些必要的方法后需要把服务包装起来以便部署到JAVA运行环境。区域相关的服务是基于标准的JAVA扩展机制(http://java.sun.com/javase/6/docs/technotes/guides/extensions/)把它们打包进 JAR 文件并放到 JRE 的扩展目录中,运行环境就能提供当初那些不被支持的区域相关的数据了。
归一化文本
---------------
Unicode 标准允许用户以不同的方式创建等效的文本。比方讲,é 这个字符是带重音的拉丁小字母,它在Unicode编码表上的码值是 U+00E9。基本字符 e 和重音符号被合成到一个编码上来表示。
也能把小写字母e和重音符号合并起来展现同样的可见字符。比如,1/2 这样的字符串就有3个字符,它与作为单个字符的1/2(unicode字符 U+00BD)其实表示了同样的意思。类似地,上标字符2与常规字符2是同样的意思,仅是在外观表现上有点不同罢了,正因为字符的这些特点,我们可以使用很多方式来进行文本的输入。你可能想到,像文本搜索和排序是不是会因为同样的字符而表象变得复杂起来呢?
Java 中的java.text.Collator 能正确领会Unicode 编码并且会将文本进行“归一化”以实现正确的搜索功能。为了执行文本的正确操作,需要把各不相同的文本转化到单一的形式。在 JDK1.6前,java.text.Collator 使用私有的 API 执行文本归一化,在1.6版本中,这些API成为了公开方法了。
用java.text.Normalizer来对文本执行归一化操作,在进行文本处理,串行化,转换甚至是数据库存储操作前进行归一化工作。java.text.Normalizer 类里只有两个静态方法:normalize 和 isNormalized 。正如所想,normalize 方法对文本执行归一化,isNormalized方法检查文本是否已经被归一化。
枚举型 Normalizer.Form 表示了每个unicode 归一化形式:
* NFD (Normalization Form D)
* NFC (Normalization Form C)
* NFKD (Normalization Form KD)
* NFKC (Normalization Form KC)
NFD是规范分解,按照unicode标准把合并了的字符分解成合并了的序列。拿unicode码 U+00F1(ñ ),会被分解成 U+006E U+0303,这个分解后的序列其实就是字符n和发音符号。
NFC是紧随规范合成后的规范分解。把文本分解后,接下来把字符序列合并到标准代码。比如把字符序列 U+0065 U+0300 并成单个字符编码 U+00E8,也就是字符 è 。NFC是W3C组织推荐的用于互联网上文本传输和处理的归一化方式。
NFKD是一种兼容性的分解。这种方式把某些字符转换到兼容的形式。通过预定义的字符映射来实现兼容。常见的商标字符 TM,其unicode 码是 U+2122,也就是大写的拉丁字符 T(U+0054)和M(U+004D)
NFKC是一种兼容的分解方式。这种归一化方式试图创建兼容原始字符的合并字符。等效的兼容字符由unicode标准定义。把NFKC应用到 U+1E9B (拉丁小写长音字符s,带有圆点上标),分解的时候就创建 U+017F U+0307 两个字符序列,最后,进行合并而成为单个字符 U+1E61
示例代码演示了如何使用Mormalizer类来把文本归一化到NFD形式:
String strName = "Jos\u00E9"; // using a composed é
String strNFD = Normalizer.normalize(strName, Normalizer.Form.NFD);
变量 strNFD 现在有五个码:Jose' 这五个码是: U+004A U+006F U+0073 U+0065 U+0301接着看看文本是否已经被归一化了:
boolean bNormalized = Normalizer.isNormalized(strNFD, Normalizer.Form.NFD);
System.out.printf("NFD? %b\n", bNormalized);
国际域名
------------------------
RFC 3490为应用程序里的国际域名(IDNA)做定义,事实上,国际域名不在仅限于ASCII码了,根据unicode 3.2 规范,域名定义的限制比原先要少了:unicode 3.2 规范中的所有字符都能用来作域名。很遗憾,域名服务器以及定位服务对于unicode 3.2还不能妥善的存储和使用非ASCII字符的信息。IDNA 的解决方式是:定义一个用ASCII编码来表示非ASCII字符的方法,这就使得DNS和名称定位服务的应用软件继续提供兼容ASCII码的服务,通过使用扩展的unicode字符,集终端用户还能使用国际化域名。
查看本文来源