使用Java语言进行Unicode代理编程

早期 Java 版本使用 16 位 char 数据类型表示 Unicode 字符。这种设计方 法有时比较合理,因为所有 Unicode 字符拥有的值都小于 65,535 (0xFFFF), 可以通过 16 位表示。但是,Unicode 后来将最大值增加到 1,114,111 (0x10FFFF)。由于 16 位太小,不能表示 Unicode version 3.1 中的所有 Unicode 字符,32 位值 — 称为码位(code point) — 被用于 UTF-32 编码模式。

但与 32 位值相比,16 位值的内存使用效率更高, 因此 Unicode 引入了一个种新设计方法来允许继续使用 16 位值。UTF-16 中采 用的这种设计方法分配 1,024 值给 16 位高代理(high surrogate),将另外 的 1,024 值分配给 16 位低代理(low surrogate)。它使用一个高代理加上一 个低代理 — 一个代理对(surrogate pair) — 来表示 65,536 (0x10000) 和 1,114,111 (0x10FFFF) 之间的 1,048,576 (0x100000) 值 (1,024 和 1,024 的乘积)。

Java 1.5 保留了 char 类型的行为来表 示 UTF-16 值(以便兼容现有程序),它实现了码位的概念来表示 UTF-32 值。这个扩展(根据 JSR 204:Unicode Supplementary Character Support 实现) 不需要记住 Unicode 码位或转换算法的准确值 — 但理解代理 API 的正 确用法很重要。

东亚国家和地区近年来增加了它们的字符集中的字符数 量,以满足用户需求。这些标准包括来自中国的国家标准组织的 GB 18030 和来 自日本的 JIS X 0213。因此,寻求遵守这些标准的程序更有必要支持 Unicode 代理对。本文解释相关 Java API 和编码选项,面向计划重新设计他们的软件, 从只能使用 char 类型的字符转换为能够处理代理对的新版本的读者。

顺序访问

顺序访问是在 Java 语言中处理字符串的一个基本操作。在 这种方法下,输入字符串中的每个字符从头至尾按顺序访问,或者有时从尾至头 访问。本小节讨论使用顺序访问方法从一个字符串创建一个 32 位码位数组的 7 个技术示例,并估计它们的处理时间。

示例 1-1:基准测试(不支持代 理对)

清单 1 将 16 位 char 类型值直接分配给 32 位码位值,完全没 有考虑代理对:

清单 1. 不支持代理对

int[]  toCodePointArray(String str) { // Example 1-1
  int len  = str.length();     // the length of str
  int[] acp  = new int[len];    // an array of code points

  for (int i = 0, j = 0; i < len; i++) {
     acp[j++] = str.charAt(i);
  }
  return acp;
}

尽管这个示例不支持代理对,但它提供了一个处理时间基准来比 较后续顺序访问示例。

示例 1-2:使用 isSurrogatePair()

清单 2 使用 isSurrogatePair() 来计算代理对总数。计数之后,它分配足够的内存 以便一个码位数组存储这个值。然后,它进入一个顺序访问循环,使用 isHighSurrogate() 和 isLowSurrogate() 确定每个代理对字符是高代理还是低 代理。当它发现一个高代理后面带一个低代理时,它使用 toCodePoint() 将该 代理对转换为一个码位值并将当前索引值增加 2。否则,它将这个 char 类型值 直接分配给一个码位值并将当前索引值增加 1。这个示例的处理时间比 示例 1 -1 长 1.38 倍。

清单 2. 有限支持

int[]  toCodePointArray(String str) { // Example 1-2 
  int len  = str.length();     // the length of str
  int[]  acp;            // an array of code points
   int surrogatePairCount = 0;   // the count of surrogate  pairs

  for (int i = 1; i < len; i++) {
    if (Character.isSurrogatePair(str.charAt(i - 1),  str.charAt(i))) {
      surrogatePairCount++;
       i++;
    }
  }
  acp = new int[len -  surrogatePairCount];
  for (int i = 0, j = 0; i <  len; i++) {
    char ch0 = str.charAt(i);     //  the current char
    if (Character.isHighSurrogate(ch0)  && i + 1 < len) {
      char ch1 =  str.charAt(i + 1); // the next char
      if  (Character.isLowSurrogate(ch1)) {
        acp[j++] =  Character.toCodePoint(ch0, ch1);
        i++;
         continue;
      }
    }
     acp[j++] = ch0;
  }
  return acp;
}

时间: 2024-08-04 09:32:57

使用Java语言进行Unicode代理编程的相关文章

java语言学习002_面向对象编程思想

      人类在认识世界时,为了方便自己和智慧提升,很自然的对事物进行了分类.对世界进行了抽象,若把所有各个事物看做对象,纵观所有对象,这些对象具有各自的或共有的特征,并且又有共有的或各自的的能力,这样就可以对具有相同一些特征和一些能力的事物进行了归类.       比如,车,有汽车,火车他们都有哪些属性?                  汽车,特征:长度,颜色,速度,轮胎,载重,平面行走--能力:移动,载东西,--                  火车,特征:长度,颜色,速度,轮胎,载重

JAVA语言编程格式高级规范_java

作为一位开发人员,都要有严格的代码规范.为此我总结了一些代码规范案例. 目 录 1. 前言 2. 试用范围 3. JAVA命名规范-- 3.1 公共约定 3.2 Java文件.包 3.3 类.接口命名规范 3.4 方法命名规范 3.5 常量 3.6 变量和参数 3.7 组件/部件 3.8 集合 3.9 神秘的数 3.10 其他 3.11 Java异常 3.12 数组命名 3.13 数据库表命名规则 3.14 数据库字段命名规则 3.15 JSP文件命名 3.16 Servlet类命名 4. 书写

实时Java,第1部分: 使用Java语言编写实时系统

由于很多重要原因,Java 语言在实时系统中的应用非常有限.这些原因包括 Java 语言设计中固有的不确定性性能影响,例如动态类加载,以及 Java 运行时环境(Java Runtime Environment,JRE)本身的不确定性性能影响,例如垃圾收集器和本地代码编译.Real-time Specification for Java (RTSJ) 是一种开放的规范,它进一步增强了 Java 语言的开放性,使它能够用来构建实时系统(参见 参考资料).要实现 RTSJ 规范,要求具备操作系统.J

java编程小说上传-java语言编程小说的上传模块不会做了,请指点

问题描述 java语言编程小说的上传模块不会做了,请指点 用java语言在编程小说的上传功能出现了问题,还请问下一步咋搞? 解决方案 报错的是什么部分错误代码帖出来,上传可以找些io方面的看看 解决方案二: 错误的地方会有信息,可以看看 解决方案三: novel没定义,还是外面定义好了,没传参进来?

java 编程-java语言求助,遇到个小问题

问题描述 java语言求助,遇到个小问题 始终提示非法字符,不知道哪里错了,各位精英帮帮忙.好像是引号的问题,大家帮忙看看. 解决方案 检查一下是不是半角与全角的原因 解决方案二: 找到提示出错的行,看看那一行都有什么符号.也可以复制贴出来才好分析. 解决方案三: 编写代码时把输入法设置成英文输入法,如果你的代码不多的话,删除重新写试试. 解决方案四: 一般编译器会把有语法错误的地方标注

Java语言的接口与类型安全_JSP编程

接口是实现构件可插入性的关键,可插入构件的关键在于存在一个公用的接口,以及每个构件实现了这个接口. 什么是接口? Java中的接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能). 接口的两种含义:一,Java接口,Java语言中存在的结构,有特定的语法和结构:二,一个类所具有的方法的特征集合,是一种逻辑上的抽象.前者叫做"Java接口",后者叫做"接口"

Java语言中字符的处理

山西省网络管理中心任军 ----摘要:本文主要讨论了Java语言中字符的特殊表达形式,尤其是中文信息的表达处理,阐述了字符处理的关键是要将十六位Unicode字符,转换为本地下层平台,也就是运行Java虚拟处理机的平台能够理解的字符形式. ----关键词:Java.字符.8位.16位.Unicode字符集 ----Java是一种编程语言.一个运行系统.一套开发工具和一个应用程序编程界面(API).Java建立在C++的熟悉.有用的特征之上,而取消了C++的复杂的.危险的和多余的元素.它是一个更安

《Java语言导学(原书第6版)》一一3.1 变量

3.1 变量 根据第2章可知,对象的状态存储在字段中: 2.1节已经介绍了字段的概念,但读者仍可能会问:命名字段有什么规则和约定?除了整型,是否还有其他数据类型?字段在声明时是否必须初始化?如果字段没有显式初始化,该字段是否会被赋予一个默认值?本章将会详细解答这些问题.但在此之前,先要明确一些技术差别.Java程序语言同时使用字段和变量.对于新的开发人员而言,这是造成概念混淆的主要原因,因为两者经常看似指代同一个事物.Java程序语言定义了如下变量: 实例变量(非静态字段).就技术而言,对象将个

《Java语言导学(原书第6版)》一3.1 变量

3.1 变量 根据第2章可知,对象的状态存储在字段中: 2.1节已经介绍了字段的概念,但读者仍可能会问:命名字段有什么规则和约定 除了整型,是否还有其他数据类型?字段在声明时是否必须初始化?如果字段没有显式初始化,该字段是否会被赋予一个默认值?本章将会详细解答这些问题.但在此之前,先要明确一些技术差别.Java程序语言同时使用字段和变量.对于新的开发人员而言,这是造成概念混淆的主要原因,因为两者经常看似指代同一个事物.Java程序语言定义了如下变量: 实例变量(非静态字段).就技术而言,对象将个