字符编码基本概念
1、ASCII编码,就是英文显示文字所需要的256个字符(比如,英文字母、数字、标点符号等等)
2、ANSI编码,像中文,肯定不能只用256个字符就代表所有汉字。因此对ASCII码表进行了扩展,使用两个(或多个)字节,代表一个汉字。类似的,不同的国家和地区制定了不同的标准,这些使用 2 个字节来代表一个字符的各种延伸编码方式,称为 ANSI 编码。也就是说,ANSI是一种对ASCII码表进行扩展的泛称,不同语言操作系统,其代表的编码方式不一样。比如中文操作系统,ANSI编码就代指GB2312;日文操作系统ANSI编码就代指JIS。
3、Unicode编码,Unicode是一个超大的集合,也是一个统一的标准,可以容纳世界上的所有语言符号。每个符号的编码都不一样,比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,“汉”这个字的Unicode编码是U+6C49。
4、代码页(codepage),Unicode是一个世界统一的标准,也就是说,如果一个文本是用Unicode方式编码的,那么它可以同时显示中文、日文、阿拉伯文等等,并且是在任何系统上都可以正常显示的。但是由于ANSI编码之间互不兼容,因此就需要有一个标识来表明不同的ANSI编码到Unicode之间的映射关系(也就是不同编码之间的映射关系),这个就是代码页。比如简体中文的代码页是CP_936(中文系统默认的代码页),这个也就是windows API中MultiByteToWideChar第一个参数所代表的含义。如果不标明代码页,系统是不知道如何进行编码转换的。
5、SBCS(单字节字符集),MBCS(多字节字符集),DBCS(宽字节字符集),分别对应上面提到的ASCII编码、ANSI编码、Unicode编码。
6、中文常见编码:GB2312(CP_20936)->GBK(CP_936)->GB18030(CP_54936),三种编码方式向下兼容,也就是说GB18030包含GB2312的所有字符。GB18030在2000年取代GBK成为正式国家标准。
7、UCS(Unicode Character Set):UCS-2规定了2个字节代表一个文字,还有UCS-4规定了4个字节代表一个文字。我们工作中几乎总是在和UCS-2打交道。
8、UTF(UCS Transformation Format):UCS只是规定的如何编码,但是没有规定如何传输、保存这个编码。UTF则规定了由几个字节保存这个编码。UTF-7,UTF-8,UTF-16都是比较常见的编码方式。UTF-8编码与Unicode编码并不相同,但是它们之间可以通过计算进行转换,而不像ANSI和Unicode之间必须通过一个映射表来人为规定其对应关系。UTF-16完全对应于UCS-2,并可通过计算代表一部分UCS-4文字。还有UTF-32则是完全对应于UCS-4,不过很不常见就是了。
9、UTF-8是与ASCII码兼容的,英文字母1个字节,汉字通常是3个字节;UTF-16的所有字符都是用2个字节进行保存,其编码与Unicode是等价的。UTF-16又分为UTF-16LE(little endian)和UTF-16BE(big endian),比如一个字母’a',如果按utf-8来存,就是0×61;如果按utf-16le来存就是0×61 0×00(低有效位在前);如果按utf-16be来存就是0×00 0×61(高有效位在前)。这个也就是我们用记事本另存文件的时候可以选择的几个编码方式的含义。
10、BOM(byte order mark),上面提到的utf-8 utf-16le utf16-be都是unicode编码,但是系统依然无**确解析一个文本文件,即便已经知道它是unicode编码。所以就有了这样的规定:在文本文件的最开头插入几个字节的标识,来说明编码方式。utf-8的BOM是0xef 0xbb 0xbf,utf-16le的BOM是0xff 0xfe,utf16-be的BOM是0xfe 0xff。事实上BOM并不是必须的,它仅仅是帮助程序自动判断编码方式使用的,如果我们手动选择编码方式(像ANSI一样),即便没有BOM,也是可以正常显示的。反过来说,程序读文本文件的时候要先读文本开始的三个字节判断下编码方式。