文件编码

最近学习python,遇到了不少和字符编码有关的问题,所以特地查了不少资料,学习了不少知识,所以就借此机会整理了一下。

  • 字符(Character):是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。
  • 字符集(Character set):是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、GB18030字符集、Unicode字符集等。
  • 字符编码(Character Encoding):是一套法则,使用该法则能够对自然语言的字符的一个集合(如字母表或音节表),与其他东西的一个集合(如号码或电脉冲)进行配对。即在符号集合与数字系统之间建立对应关系。

ASCII

ASCII字符集,共表示了128个字符,包括32个不能打印的字符。
ASCII编码,将ASCII字符集转换成计算机能够接受的数字系统的数的规则。采用八位二进制编码,最高位统一为0,剩余7位共表示了128个字符,包括32个不能打印的字符,如:500110101来表示,如果文件是ASCII编码,可以在DOS中通过type命令查看。
另:ASCII的扩展版本EASCII可以显示西欧语言,是现今最通用的单字节编码系统。

GB类

由于ASCII编码不支持中文,所以中国单独制定了一套编码。

  • GB2312编码,使用两个字节,一共收录了7445个字符,包括6763个汉字和682个其他字符。这682个其他字符包括:罗马希腊字母,数学符号,日文假名,数字(全角),标点(全角),字母(全角)。汉字区的内码范围高字节从B0-F7,低字节从A1-FE。ASCII里面本来就有的叫做半角
  • GBK编码(1.0),微软编制,是对GB2312的扩展,收录了21886个符号。
  • GB18030编码,基本兼容GBK,完全兼容GB2312,,支持Unicode的全部统一汉字,收录了70244个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。

以上三种(GB2312,GBK,GB18030)被称为双字节字符集(DBCS)

兼容性:

ASCII < GB2312 < GBK < GB18030 如:字均用6C49来表示。
ASCII < Unicode 如:字用BABA来表示

Big5

大五码,是使用繁体中文最常用的电脑汉字字符集标准。


像中国一样,各个国家都有类似GB2312编码的编码体系,这样非常不适合交流。于是就出现了大一统。历史上有两个组织开发出了统一的编码系统,分别是国际标准化组织(ISO)和统一码联盟(The Unicode Consortium),分别研制出了UCS(ISO 10646)和Unicode。目前两个项目保持兼容。


Unicode字符集

Unicode字符集,两字节二进制编码,如:U+6C49来表示。

big endian U+6C49来表示,文件最前面有一个FEFF
little endian U+496C来表示,文件最前面有一个FFFE
Unicode字符集有很多种编码方案,比如:UTF-8,UTF-16,UTF-32等

UCS(通用字符集)

Universal Character Set,通用字符集。是由ISO 10646标准所定义的标准字符集,包含已知语言的所有字符。

UCS-2,用16位编码。
UCS-4,用31位编码,第32位为0。

下面介绍下UCS-4
0xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx 共有 2^31 = 2147483648 个码位。

  • UCS-4编码分为2^7 = 128 个group,每个group形如 01234567 xxxxxxxx xxxxxxxx xxxxxxxx
  • 每个group分为2^8 = 256 个plane,每个plane形如 01234567 12345678 xxxxxxxx xxxxxxxx
  • 每个plane分为2^8 = 256 个rows,每个rows形如 01234567 12345678 12345678 xxxxxxx
  • 每个rows分为2^8 = 256 个cells,每个cells形如 01234567 12345678 12345678 12345678

00000000 00000000 xxxxxxxx xxxxxxxx ,即高两个字节均为0的UCS-4被称为BMP

UTF-8编码方式

UTF-8(8-bit Unicode Transformation Format),可变长度字符编码,是unicode的一种实现方式。与ASCII编码兼容。
占用1~4个字节
编码规则:

  • 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
  • 对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
UCS-2编码(16进制)/Unicode符号范围 UTF-8 字节流(二进制)
0000 0000 - 0000 007F 0xxxxxxx
0000 0080 - 0000 07FF 110xxxxx 10xxxxxx
0000 0800 - 0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000 - 0010 FFFF 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx

例如“汉”字的Unicode编码是6C49,故转化成UTF-8采用第三种三字节编码方式,6C49的二进制带入三字节模版,就得到了其UTF-8编码:11100110 10110001 10001001,即E6 B1 89
UTF编码中有一个名为BOM的编码方式,用来区分UTF-16是Big-Endian还是Little-Endian。

UTF-16编码方式

UTF-16编码方式用16位,即两个字节来编码字符,所以他只能编码Unicode的前65535个字符。

  • 如果字符编码小于0x10000,直接用两字节表示,如U+6C49
  • 如果字符编码大于0x10000

UTF-32编码方式

UTF-32又称UCS-4,是一种将Unicode字符编码的协定,对每个字符使用4个字节。这种编码方式非常浪费空间。

CJK

Chinese Japanese Korean,中日韩统一表意文字。把分别来自中文、日文、韩文、越文中,本质、意义相同、形状一样或稍异的表意文字(主要为汉字,但也有仿汉字如日本国字、韩国独有汉字、越南的喃字)于ISO 10646及Unicode标准内赋予相同编码。

windows和linux种的文件编码

windows中新建一个记事本文档,默认是ASCII编码,如果出现中文就会使用gb2312编码。
linux编码使用utf-8编码。

mySQL的编码

mySQL默认采用ISO 8859-1编码方式,即单字节的EASCII编码。
更改mySQL编码方式:mysql_query('set names gbk');

参考资料