char类型和Unicode编码

【0】README
0.1)本文对 char类型和Unicode编码 的总结并不完整,仅供参考;
0.2)本文获取Unicode辅助字符的代码点的idea转自: 

【1】char 类型
1)char类型:它用于表示单个字符, 通常用来表示字符常量;
2)Unicode编码单元: 它可以表示为16进制值, 其范围从 \u0000 ~ \uffff; 如\u03C0 表示希腊字母 π;
3)转移序列:
3.1)除了可以采用转义序列符 \u 表示Unicode 代码单元的编码外, 还有一些用于表示特殊字符的转移序列符,看下表:
3.2)所有这些转义序列符都可以出现在字符常量或字符串的引号内;如'\u2122' 和 "hello\n";
3.3)转移序列符 \u 还可以出现在 字符常量或字符串的引号之外(其他的转移序列不可以), 如 public static void main(String \u005B\u005D args) ,其中 \u005B 和 \u005D 是 '[' 和 ']' 的编码;
4)出现的问题+解决方法(引入Unicode编码):
4.1)要想弄清char类型, 就必须了解Unicode编码表(干货——引入了Unicode编码表)Unicode打破了传统字符编码的限制。在Unicode出现之前, 已经有许多不同的标准:美国的ASCII、西欧语言的ISO、中国的GB 18030 和 BIG-5 等, 这样就产生了两个问题:一是对于任意给定的代码值,在不同的编码方案下有可能对应不同的字母; 二是采用大字符集的语言其编码长度有可能不同;(如一些字符采用单字节编码,而另一些字符采用多字节编码)
4.2)如何解决:人们认为两个字节的代码宽度足以能够对世界上各种语言的所有字符进行编码, 并有足够的空间留给未来的扩展;
4.3)1991年,发布的Unicode1.0 : 仅占用了 65535个代码值中不到一半的部分,在设计Java时 决定采用16位的Unicode 字符集;但是后来Unicode 增加了对汉语、日语和韩语的处理使得字符个数超过了 65536, 这样使得 Java的16位的 char 类型已经不能满足描述所有 Unicode字符的需要了;
5)下面用专业术语解释Java语言解决这个问题的基本方法:
5.1)代码点: 从JDK5.0开始, 代码点是指与一个编码表中的某个字符对应的代码值;在Unicode标准中, 代码点采用16进制书写,并加上前缀 U+, 例如 U+0041 表示字符A的代码点;(干货——代码点的定义)
5.2)代码级别:Unicode的代码点可以分成17 个代码级别, 第一个代码级别称为基本的多语言级别, 代码点从 U+0000~U+FFFF;其余的16个附加级别,代码点从U+10000~U+10FFFF, 其中包括了一些辅助字符;(干货——代码级别的定义)
5.3)代码单元:在UTF-16中, 每个字符用16位表示,这叫一个代码单元;而辅助字符采用一对连续的代码单元进行编码;(干货——代码单元的定义,一个Unicode代码单元==16位==2个字节)
5.4)这样构成的编码值:一定落入基本的多语言级别中空闲的2048字节内,通常被替代区域(U+D800~U+DBFF用于第一个代码单元,而U+DC00~U+DFFF用于第二个代码单元)。这样的设计十分巧妙,我们可以从中迅速知道一个代码单元是一个字符编码,还是一个辅助字符的第一或第二部分。
看个Unicode字符的编码荔枝)对于整数集合的数学符号Z, 它的代码点是 U+1D56B,并且是用两个代码单元U+D835 和 U+DD6B 编码的;(具体参见 https://en.wikipedia.org/wiki/UTF-16
6)Java采用UTF-16:在Java中, char类型用 UTF-16 编码描述一个代码单元;(干货——char类型用UTF-16 编码描述一个代码单元,char类型就是一个Unicode代码单元, Unicode码元==Unicode代码单元)
7)Warning)我们强烈建议,不要在程序中使用char类型, 除非确实需要对 UTF-16代码单元进行操作。最好将 需要处理的字符串用抽象数据类型表示;

【2】Unicode编码中的代码点和代码单元 
1)Java 字符串由char 序列组成: char数据类型是一个采用 UTF-16 编码表示 Unicode代码点的代码单元, 大多数的常用 Unicode字符使用一个代码单元就可以表示, 而辅助字符需要一对代码单元表示;
2)length方法: 它将返回采用 UTF-16 编码表示的给定字符串所需要的代码单元数量;
3)看荔枝:
package com.tomcat.test;

public class UnicodeTest {
	public static void main1(String[] args) {
		String greeting = "hello";
		System.out.println(greeting.length()); // Unicode代码单元(码元)数量 // 5
		int codePointCount = greeting.codePointCount(0, greeting.length());
		System.out.println(codePointCount); //Unicode代码点数量 // 5
		char first = greeting.charAt(0);// 返回位置0的代码单元 // 'h'
		System.out.println(first);
		// 要想得到第i个代码点
		for (int i = 0; i < greeting.length(); i++) {
			int index = greeting.offsetByCodePoints(0, i);
			int codePoint = greeting.codePointAt(index);
			System.out.println("index = " + index + ", codePoint = " + codePoint + ", " + (char)codePoint);
		}
		/**
		 * output
		 *  5
			5
			h
			index = 0, cp = 104, h
			index = 1, cp = 101, e
			index = 2, cp = 108, l
			index = 3, cp = 108, l
			index = 4, cp = 111, o
		 */
	}
	
	public static void main2(String[] args) {
		String sentence = "\u1D56B is the set of integers";
		for (int i = 0; i < sentence.length();) {
			int codePoint = sentence.codePointAt(i);
			if(Character.isSupplementaryCodePoint(codePoint)) {
				i += 2;
			} else {
				i++;
			}
			System.out.println(codePoint + ", " + (char)codePoint);
		}
	}
	
	public static void main3(String...args){       
        char[] ch = Character.toChars(0x10400);  
        System.out.printf("U+10400 高代理字符: %04x\n", (int)ch[0]);//d801  
        System.out.printf("U+10400 低代理字符: %04x\n", (int)ch[1]);//dc00     
        String str = new String(ch);  
        System.out.println("代码单元长度: " + str.length());//2  
        System.out.println("代码点数量: " + str.codePointCount(0, str.length()));//1  
        System.out.println(str.codePointAt(0));//返回给定位置开始或结束的代码点,66560  
        System.out.println(str.charAt(1));//返回给定位置的代码单元,由于未定义,返回?  
          
        //遍历一个字符串,打印出所有字符的代码点  
        str += "Hello,world!";  
        int i = 0;  
        int cp = str.codePointAt(i);  
        while(i < str.length()){  
            System.out.println(str.codePointAt(i) + ", " + (char)str.codePointAt(i));  
            if(Character.isSupplementaryCodePoint(cp))  
                i += 2;//如果cp所在的位置是代码点的第一部分,执行此处  
            else i++;  
        }  
        /* 
         * 66560  
         * 72  
         * 108  
         * 111  
         * 119  
         * 114  
         * 100 
         */  
    }  	 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值