字符集(Charcater Set)与字符编码(Encoding)

来源:互联网 发布:英伦风淘宝店 编辑:程序博客网 时间:2024/06/03 17:59

字符集(Charcater Set或Charset):是一个系统支持的所有抽象字符的集合,也就是一系列字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。常见的字符集有:ASCII字符集、GB2312字符集(主要用于处理中文汉字)、GBK字符集(主要用于处理中文汉字)、Unicode字符集等。

字符编码(Character Encoding):是一套法则,使用该法则能够对自然语言的字符的一个字符集(如字母表或音节表),与计算机能识别的二进制数字进行配对。即它能在符号集合与数字系统之间建立对应关系,是信息处理的一项基本技术。通常人们用符号集合(一般情况下就是文字)来表达信息,而计算机的信息处理系统则是以二进制的数字来存储和处理信息的。字符编码就是将符号转换为计算机能识别的二进制编码。

一般一个字符集等同于一个编码方式,ANSI体系(ANSI是一种字符代码,为使计算机支持更多语言,通常使用 0x80~0xFF 范围的 2 个字节来表示 1 个字符)的字符集如ASCII、ISO 8859-1、GB2312、GBK等等都是如此。一般我们说一种编码都是针对某一特定的字符集。 
一个字符集上也可以有多种编码方式,例如UCS字符集(也是Unicode使用的字符集)上有UTF-8、UTF-16、UTF-32等编码方式。

从计算机字符编码的发展历史角度来看,大概经历了三个阶段: 
第一个阶段:ASCII字符集和ASCII编码。 
计算机刚开始只支持英语(即拉丁字符),其它语言不能够在计算机上存储和显示。ASCII用一个字节(Byte)的7位(bit)表示一个字符,第一位置0。后来为了表示更多的欧洲常用字符又对ASCII进行了扩展,又有了EASCII,EASCII用8位表示一个字符,使它能多表示128个字符,支持了部分西欧字符。

第二个阶段:ANSI编码(本地化) 
为使计算机支持更多语言,通常使用 0x80~0xFF 范围的 2 个字节来表示 1 个字符。比如:汉字 ‘中’ 在中文操作系统中,使用 [0xD6,0xD0] 这两个字节存储。 
不同的国家和地区制定了不同的标准,由此产生了 GB2312, BIG5, JIS 等各自的编码标准。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。 
不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。

第三个阶段:UNICODE(国际化) 
为了使国际间信息交流更加方便,国际组织制定了 UNICODE 字符集,为各种语言中的每一个字符设定了统一并且唯一的数字编号,以满足跨语言、跨平台进行文本转换、处理的要求。UNICODE 常见的有三种编码方式:UTF-8(1个字节表示)、UTF-16((2个字节表示))、UTF-32(4个字节表示)。

我们可以用一个树状图来表示由ASCII发展而来的各个字符集和编码的分支: 各种类型的编译


Unicode Character Set与Multi-Byte Character Set有什么区别呢?

Unicode Character Set和Multi-Byte Character Set这两个设置有什么区别呢?我们来看一个例子: 
有一个程序需要用MessageBox弹出提示框:

<code class="language-C++ hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">#include</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"windows.h"</span> <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">void</span> TestMessageBox() { <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::MessageBox</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NULL</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"这是一个测试程序!"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Title"</span>, MB_OK); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

上面这个Demo非常简单不用多说了吧!我们将Character Set设置为Multi-Byte Character Set时,可以正常编译和运行。但当我们设置为Unicode Character Set,则会有以下编译错误:

error C2664: ‘MessageBoxW’ : cannot convert parameter 2 from ‘const char [18]’ to ‘LPCWSTR’

这是因为MessageBox有两个版本,一个MessageBoxW针对Unicode版的,一个是MessageBoxA针对Multi-Byte的,它们通过不同宏进行隔开,预设不同的宏会使用不同的版本。我们使用了Use Unicode Character Set就预设了_UNICODE、UNICODE宏,所以编译时就会使用MessageBoxW,这时我们传入多字节常量字符串肯定会有问题,而应该传入宽符的字符串,即将”Title”改为L”Title”就可以了,”这是一个测试程序!”也一样。

<code class="hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">WINUSERAPI int WINAPI MessageBoxA( __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span>_opt HWND hWnd, __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span>_opt LPCSTR lpText, __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span>_opt LPCSTR lpCaption, __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> UINT uType); WINUSERAPI int WINAPI MessageBoxW( __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span>_opt HWND hWnd, __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span>_opt LPCWSTR lpText, __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span>_opt LPCWSTR lpCaption, __<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> UINT uType); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#ifdef UNICODE</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#define MessageBox MessageBoxW</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#else</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#define MessageBox MessageBoxA</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#endif // !UNICODE</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li></ul>

上面的Multi-Byte Character Set一般是指ANSI(多字节)字符集,关于ANSI请参考第二小节字符集(Charcater Set)与字符编码(Encoding)。而Unicode Character Set就是Unicode字符集,一般是指UTF-16编码的Unicode。也就是说每个字符编码为两个字节,两个字节可以表示65535个字符,65535个字符可以表示世界上大部分的语言。

一般推荐使用Unicode的方式,因为它可以适应各个国家语言,在进行软件国际时将会非常便得。除非在对存储要求非常高的时候,或要兼容C的代码时,我们才会使用多字节的方式 。