在最近的项目中,遇到了UTF-8编码的问题。在Oracle的数据库表中有一个字段,数据类型为NVARCHAR2,长度为2000字,用于汉字存储,在超过1300字的时候会提示错误,在网上搜索了一下,有人说是在UTF-8中汉字编码为三个字节,也有人说是两个或三个字节,还有人说也有四个字节的。在下水平有限,欢迎各位大侠指教!
今天受到我最最最最最最崇拜的同学的指教以后,终于把UTF-8字符集编码搞明白了,我对他的敬仰有如滔滔江水,连绵不绝,有如黄河泛滥,一发不可收拾呀。
使用Unicode编码,一个英文字符要占用2个字节。在Internet上,大多数信息都是用英文来表示的。如果用unicode编码,那么信息量将会增加1倍。为了减少存储和传输英文字符数据的数据量,可以使用UTF-8编码。
UTF-8全称是Eight-bit UCS Transformation Format(UCS university charset Set, 通用字符集,UCS是所有其他字符集的一个超集)。对于常用的字符,即0~127的ASCII字符,UTF-8用一个字节来表示,这意味着只包含7位ASCII字符的字符数据在ASCII和UTF-8两种编码方式下是一致的。如果字符对应的Unicode码是0X0000,或在0X0080与0X007f之间,对应的UTF-8码是两个字节。如果字符对应的Unicode码在0X0800与0Xffff之间,对应的UTF-8编码是3个字节。因为中文字符的Unicode编码在0X0800与0Xffff之间,所以数据如果是中文,采用UTF-8编码数据量会增加50%。
Unicode与UTF-8之间的转换规则如下:
(1)如果Unicode编码的16位二进制数的前9位是0, 则UTF-8编码用一个字节来表示,这个字节的首位是0,剩下的7位与原二进制数据的后7位相同。例如:
Unicode编码: /u0061 = 00000000 01100001
UTF-8编码: 01100001 = 0x61
(2)如果Unicode编码的16位二进制数的头5位是0,则UTF-8编码用2个字节来表示,首字节用110开头,后面的5位与原二进制数据去掉前5个零后的最高5位相同;第二个字节以10开头,后面的6位与原二进制数据的低6位数据相同。例如:
Unicode编码: /u00A9 = 00000000 10101001
UTF-8编码: 11000010 10101001 = 0xC2 0xA9
(3)如果不符合上述两个规则,则用3个字节表示。第一个字节以1110开头,后四位为原二进制数据的高四位,第二个字节以10开头,后六位为原二进制数据的中间6位,第三个字节以10开头,后6位为原二进制数据的低6位。例如:
Unicode编码: /u4E2D = 01001110 00101101
UTF-8编码: 11100100 10111000 10101101 = 0xE4 0xB8 0xAD