1.基本概念
字符集(Characterset):是一个系统支持的所有具象字符的集合。字符是各类文字和符号的统称,包括各国家文字、标点符号、图形符号、数字等。常见的字符集有ASCII、ZHS16GBK、ZHT16BIGBIG5、ZHS32GB18030字符集、Unicode字符集等。
字符编码(CharacterEncoding):是一套法则,使用该法则才能对自然语言的字符的一个集合(如字母表或韵母表),与其它的一个集合(如笔记本编码)进行配对。即在符号集合与数字系统之间构建对应关系。与字符集相对应,常见的字符编码有:ASCii,ZHS16GBK,ZHT16BIGBIG5,ZHS32GB18030等。
字符集的定义似乎就是字符的集合,而字符编码则是指如何将那些字符弄成字节用于保存、读取和传输。
2.字符集的前世此生
1)通用字符集UCS
通用字符集(UniversalCharacterSet,UCS)是由ISO拟定的ISO10646(或称ISO/IEC10646)标准所定义的字符编码方法,采用4字节编码。又称UniversalMultiple-OctetCodedCharacterSet,台湾译为通用多八位编码字符集,香港译为广用多八位元编码字元集。
通用字符集是所有包括了其他字符集。它保证了与其他字符集的单向兼容,即,假如你将任何文本字符串翻译到UCS格式,之后再翻译回原编码,你不会遗失任何信息。UCS包含了已知语言的所有字符。不仅拉丁语、希腊语、斯拉夫语、希伯来语、阿拉伯语、亚美尼亚语、乔治亚语,还包括英文、日文、韩文这样的象形文字linux 中文字符集,UCS还包括大量的图形、印刷、数学、科学符号。
通用字符集是与UNICODE同类的组织,UCS-2和UNICODE兼容。
2)Unicode编码
Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。包含了几乎人类所有可用的字符linux入门,每年还在不断的降低,可以看作是一种通用的字符集。Unicode定义了大到足以代表人类所有可读字符的字符集。Java语言就用到了Unicode编码,进而实现了该语言的国际通用性。
Unicode是基于通用字符集(UniversalCharacterSet)的标准来发展,用数字0-0x10FFFF来映射这种字符,或则说有1114112个码位(码位就是可以分配给字符的数字)。
对可以用ASCII表示的字符使用UNICODE并不高效,由于UNICODE比ASCII占用大一倍的空间,而对ASCII来说高字节的0对他毫无益处。为了解决这个问题,有人发明了一种针对UNICODE的变换规则,把UNICODE字符串中的0清除.注意这个变换规则不是通过查表实现的,而只要用一些位移操作就可以实现.这就是UTF,她们被称为通用转换格式,即UTF(UCSTransformationFormat)。常见的UTF格式有:
UTF-32编码:固定使用4个字节来表示一个字符,这些编码存在空间借助效率的问题。
UTF-16编码:对相对常用的60000余个字符使用两个字节进行编码,其余的使用4字节。
UTF-8编码:兼容ASCII编码;拉丁文、希腊文等使用两个字节;包括汉字在内的其它常用字符使用三个字节;剩下的很少使用的字符使用四个字节。
下边重点介绍下UTF-8编码:
UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方法为:将Unicode二补码从高位往低位取出二补码数字,每次取6位,如上述的二补码就可以分别取出为如下示例所示的格式linux使用教程,上面按格式弥补,不足8位用0弥补。
Unicode编码(16补码)
UTF-8字节流(二补码)
000000-00007F
0xxxxxxx
000080-0007FF
110xxxxx10xxxxxx
000800-00FFFF
1110xxxx10xxxxxx10xxxxxx
010000-10FFFF
11110xxx10xxxxxx10xxxxxx10xxxxxx
UTF-8的特性是对不同范围的字符使用不同厚度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大宽度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二补码数字。Unicode的最大码位0xx1010FFFF也只有21位。
例1:“汉”字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用3字节模板了:1110xxxx10xxxxxx10xxxxxx。将0x6C49写成二补码是:01001,用这个比特流依次取代模板中的x,得到:10,即E6B189。
例2:Unicode编码0x20C30在0x010000-0x10FFFF之间,使用用4字节模板了:11110xxx10xxxxxx10xxxxxx10xxxxxx。将0x20C30写成21位二补码数字(不足21位就在上面补0):0000110000,用这个比特流依次取代模板中的x,得到:1010110000,即F0A0B0B0。
3)ASCII
ASCII(AmericanStandardCodeforInformationInterchange,新加坡信息互换标准代码)是ANSI(AmericanNationalStandardsInstitute)意大利国家标准学会的规范标准,世界上所有的计算机都用同样的ASCII方案来保存中文文字。由于ASCII没有可以借助的字节状态来表示汉字,
中国人在ASCII的基础上,通过组合的形式,组合不仅大概7000多个繁体汉字,把这些方案叫GB2312,GB2312是对ASCII的英文扩充。
4)GB2312
英文文字数量大,并且还分为繁体英文和简体英文两种不同书写规则的文字,而计算机最初是按英文单字节字符设计的,为此,对英文字符进行编码,是英文信息交流的技术基础。
我国国家标准总局1980年发布《信息交换用汉字编码字符集》,标准号是GB2312—1980,它是计算机可以辨识的编码,适用于汉字处理、汉字通讯等系统之间的信息交换。基本集共收入汉字6763个和非汉字图形字符682个。
GB2312的出现,基本满足了汉字的计算机处理须要,它所收录的汉字早已覆盖中国内地99.75%的使用频度。
1995年国家标准总局又出台了《汉字编码扩充规范》(GBK)。GBK与GB2312—1980国家标准所对应的内码标准兼容。
对于人名、古汉语等方面出现的罕用字,GB2312不能处理,这造成了后来GBK及GB18030汉字字符集的出现。
注意:
UTF8只是UNICODE内码在储存/传输时的状态.而从GB2312编码转换到UNICODE编码须要查表.UTF8和UNICODE的关系与GB2312和UNICODE的关系有本质的不同.UTF8和UNICODE是一个人的两个脸孔,GB2312和UNICODE是两个人.所以,要实现UTF8编码到GB2312编码的转换必须先把UTF8编码还原为UNICODE编码,再通过查表的方法,把UNICODE编码转化为GB2312编码。
5)Latin1
Latin1是ISO-8859-1的别称,有些环境下写作Latin1,是单字节编码,向上兼容ASCII。
3.Linux字符集
提及linux字符集就不得不说locale。locale是国际化与本土化过程中的一个特别重要的概念,对于英文用户来说,一般会涉及到的国际化或则本土化,大致包含两个方面:看英文,写英文,locale的设定与看英文关系不大,而且与写英文有很密切的关系。
locale这个词组英文翻译成地区或则地域,虽然这个词组包含的意义要笼统好多。Locale是按照计算机用户所使用的语言,所在国家或则地区,以及当地的文化传统所定义的一个软件运行时的语言环境。这个用户环境可以根据所涉及到的文化传统的各个方面分成几个大类,一般包括用户所使用的语言符号及其分类(LC_CTYPE),数字(LC_NUMERIC),比较和排序习惯(LC_COLLATE),时间显示格式(LC_TIME),货币单位(LC_MONETARY),信息主要是提示信息,错误信息,状态信息,标题,标签,按键和菜单等(LC_MESSAGES),姓名书写形式(LC_NAME),地址书写形式(LC_ADDRESS),电话号码书写形式(LC_TELEPHONE),测度衡抒发形式(LC_MEASUREMENT),默认纸张规格大小(LC_PAPER)和locale对自身包含信息的概述(LC_IDENTIFICATION)。诸如:
前面均说明LC_CTYPE(语言符号及其分类)表示这个系统的系统现今使用的字符集是en_US.UTF-8,LC_NUMERIC(数字)等其它与语言相关的变量。一般假如其它的语言变量都未设定,仅设定LANG这个变量就可以缺省取代所有其它变量了。
Locale实际就是某一个地域内的人们的语言习惯和文化传统和生活习惯。一个地区的locale就是按照这几大类的习惯定义的,这种locale定义文件置于/usr/share/i18n/locales目录下边:
4.GaussDBForDWS字符集
GaussDBfordws默认使用sql_ascii作为默认字符集,ASCII储存的是单字节流,而且没有能力判定多字节字符的有效性,所以会一股脑储存进去,换句话说你可能在SQL_ASCII中储存了utf8编码的字符,也储存了gbk编码的字符,还储存了其他编码的字符.这么要将sql_ascii转换成UTF8就不是一件易事了,会遇见多种字符的转换工作。
假如数据库的编码为SQL_ASCII(可以通过“showserver_encoding”命令查看当前数据库储存编码)linux 中文字符集,则在创建数据库对象时,假如对象名中富含多字节字符(比如英文),超过数据库对象名宽度限制(63字节)的时侯,数据库将会将最后一个字节(而不是字符)截断,可能导致出现半个字符的情况。