GBK,BIG5等字符集编码局限的具体申明

831 篇文章 15 订阅
300 篇文章 0 订阅

一 筹办常识


1,字符:字符是抽象的最小文本单位。它没有固定的外形(可能是一个字形),并且没有值。“A”是一个字符,“€”(德国、法国和很多其他欧洲国度通用货币的标记)也是一个字符。”“这是两个汉字字符。字符仅仅代表一个符号,没有任何实际值的意义。
2,字符集:字符集是字符的凑集。例如,汉字字符是中国人最先发明的字符,在中文、日文、韩文和越南文的书写中应用。这也说了然字符和字符集之间的关系,字符构成字符集(iso8859-1GB2312/GBKunicode)。
3,代码点:字符集中的每个字符都被分派到一个代码点。每个代码点都有一个特定的独一数值,称为标值。该标量值凡是用十六进制默示。
4,代码单位: 在每种编码情势中,代码点被映射到一个或多个代码单位。代码单位是各个编码体式格式中的单个单位。代码单位的大小等效于特定编码体式格式的位数:
UTF-8 UTF-8 中的代码单位由 位构成;在 UTF-8 中,因为代码单位较小的缘故,每个代码点经常被映射到多个代码单位。代码点将被映射到一个、两个、三个或四个代码单位;
UTF-16 UTF-16 中的代码单位由 16 位构成;UTF-16 的代码单位大小是 位代码单位的两倍。所以,标量值小于 U+10000 的代码点被编码到单个代码单位中;
UTF-32UTF-32  中的代码单位由 32 位构成; UTF-32 中应用的 32 位代码单位足够大,每个代码点都可编码为单个代码单位;
GB18030GB18030  中的代码单位由 位构成;在 GB18030 中,因为代码单位较小的缘故,每个代码点经常被映射到多个代码单位。代码点将被映射到一个、两个或四个代码单位。
5,举例:

中国北京香蕉是个大笨伯这是我定义的aka字符集;各字符对应代码点为:
北 00000001
京 00000010
香 10000001
蕉 10000010
是 10000100
个 10001000
大 10010000
笨 10100000
蛋 11000000
中 00000100
国 00001000
下面是我定义的 zixia 编码规划(8位),可以看到它的编码中默示了aka字符集的所有字符对应的 代码单位;
北 10000001
京 10000010
香 00000001
蕉 00000010
是 00000100
个 00001000
大 00010000
笨 00100000
蛋 01000000
中 10000100
国 10001000
所谓文本文件 就是我们按必然编码体式格式将二进制数据默示为对应的文本如 00000001000000100000010000001000000100000010000001000000如许的文件。我用一个支撑 zixia编码和aka字符集的记事本打开,它就遵守编码规划显示为  香蕉是个大笨伯 
若是我把这些字符遵守GBK另存一个文件,那么则必然不是这个,而是
1100111111100011 1011110110110110 1100101011000111 1011100011110110 1011010011110011 1011000110111111 1011010110110000 110100001010

二,字符集


1, 常用字符集分类
ASCII及其扩大字符集
感化:表语英语及西欧说话。
位数:ASCII是用7位默示的,能默示128个字符;其扩大应用8位默示,默示256个字符。
局限:ASCII007F,扩大从00FF
ISO-8859-1字符集
感化:扩大ASCII,默示西欧、希腊语等。
位数:8位,
局限:从00FF,兼容ASCII字符集。
GB2312字符集
感化:国度简体中文字符集,兼容ASCII
位数:应用2个字节默示,能默示7445个符号,包含6763个汉字,几乎覆盖所有高频率汉字。
局限:高字节从A1F7, 低字节从A1FE。将高字节和低字节分别加上0XA0即可获得编码。
BIG5字符集
感化:同一繁体字编码。
位数:应用2个字节默示,默示13053个汉字。
局限:高字节从A1F9,低字节从407EA1FE
GBK字符集
感化:它是GB2312的扩大,参加对繁体字的支撑,兼容GB2312
位数:应用2个字节默示,可默示21886个字符。
局限:高字节从81FE,低字节从40FE
GB18030字符集
感化:它解决了中文、日文、朝鲜语等的编码,兼容GBK
位数:它采取变字节默示(1 ASCII24字节。可默示27484个文字。
局限:1字节从007F; 2字节高字节从81FE,低字节从407E80FE4字节第一三字节从81FE,第二四字节从3039
UCS字符集
感化:国际标准 ISO 10646 定义了通用字符集 (Universal Character Set)。它是与UNICODE同类的组织,UCS-2UNICODE兼容。
位数:它有UCS-2UCS-4两种格局,分别是2字节和4字节。
局限:今朝,UCS-4只是在UCS-2前面加了0×0000
UNICODE字符集
感化:为世界650种说话进行同一编码,兼容ISO-8859-1
位数:UNICODE字符集有多个编码体式格式,分别是UTF-8UTF-16UTF-32
,按所默示的文字分类
说话                                 字符集                                     正式名称
英语、西欧语                     ASCIIISO-8859-1                MBCS 多字节
简体中文                             GB2312                                    MBCS 多字节
繁体中文                             BIG5                                         MBCS 多字节
简繁中文                             GBK                                         MBCS 多字节
中文、日文及朝鲜语         GB18030                                  MBCS 多字节
各国说话                             UNICODEUCS                    DBCS 宽字节

三,编码


UTF-8:采取变长字节 (1 ASCII, 2 希腊字母, 3 汉字, 4 平面符号) 默示,收集传输, 即使错了一个字节,不影响其他字节,而双字节只要一个错了,其他也错了,具体如下:
若是只有一个字节则其最高二进制位为0;若是是多字节,其第一个字节从最高位开端,连气儿的二进制位值为1的个数决意了其编码的字节数,其余各字节均以10开首。UTF-8最多可用到6个字节。

UTF-16:采取2字节,Unicode中不合项目组的字符都同样基于现有的标准。这是为了便于转换。从 0×00000×007FASCII字符,从0×00800×00FFISO-8859-1ASCII的扩大。希腊字母表应用从0×0370到 0×03FF 的代码,斯拉夫语应用从0×04000×04FF的代码,美国应用从0×05300×058F的代码,希伯来语应用从0×05900×05FF的代 码。中国、日本和韩国的象形文字(总称为CJK)占用了从0×30000×9FFF的代码;因为0×00c说话及操纵体系文件名等中有特别意义,故很 多景象下须要UTF-8编码保存文本,去掉这个0×00。举例如下:
UTF-16: 0×0080  = 0000 0000 1000 0000
UTF-8:   0 xC280 = 1100 0010 1000 0000
UTF-32:采取4字节。
优毛病
UTF-8UTF-16UTF-32都可以默示有效编码空间 (U+000000-U+10FFFF) 内的所有Unicode字符。
应用UTF-8编码时ASCII字符只占1个字节,存储效力斗劲高,实用于拉丁字符较多的场合以节俭空间。
对于大多半非拉丁字符(如中文和日文)来说,UTF-16所需存储空间最小,每个字符只占2个字节。
Windows NT内核是UnicodeUTF-16),采取UTF-16编码在调用体系API时无需转换,处理惩罚速度也斗劲快。
采取UTF-16UTF-32会有Big EndianLittle Endian之分,而UTF-8则没有字节次序题目,所以UTF-8合适传输和通信。
UTF-32采取4字节编码,一方面处理惩罚速度斗劲快,但另一方面也浪费了多量空间,影响传输速度,因而很少应用。

四,如何断定字符集


1,字节序
起首说一下字节序对编码的影响,字节序分为Big Endian字节序和Little Endian字节序。不合的处理惩罚器可能不一样。所以,传输时须要告诉处理惩罚器当时的编码字节序。对于前者而言,高位字节存在低地址,低字节存于高地址;后者相反。例如,0X03AB,
Big Endian字节序
0000: 0 3
0001: AB
Little Endian字节序是
0000: AB
0001: 0 3
2,编码辨认
UNICODE,按照前几个字节可以断定UNICODE字符集的各类编码,叫做Byte Order Mask办法BOM
UTF-8: EFBBBF (合适UTF-8格局,请看上方。但没有含义在UCSUNICODE
UTF-16 Big EndianFEFF (没有含义在UCS-2
UTF-16 Little EndianFFFE (没有含义在UCS-2
UTF-32 Big Endian0000FEFF (没有含义在UCS-4
UTF-32 Little EndianFFFE0000 (没有含义在UCS-4

GB2312:高字节和低字节的第1位都是1

BIG5GBK&GB18030:高字节的第1位为1。操纵体系有默认的编码,常为GBK,可以下载此外并进级。经由过程断定高字节的第1位从而知道是ASCII或者汉字编码。


摘自: http://blog.minidx.com/2008/12/06/1689.html 


字符编码笔记:ASCIIUnicodeUTF-8


 摘自:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html  

今天正午,我忽然想搞清楚UnicodeUTF-8之间的关系,于是就开端在网上查材料。

成果,这个题目比我想象的错杂,从午饭后一向看到晚上9点,才算初步搞清楚。

下面就是我的笔记,首要用来收拾本身的思路。然则,我尽量试图写得通俗易懂,欲望能对其他伴侣有效。毕竟成果,字符编码是策画机技巧的基石,想要谙练应用策画机,就必须懂得一点字符编码的常识。

1. ASCII


我们知道,在策画机内部,所有的信息终极都默示为一个二进制的字符串。每一个二进制位(bit)有01两种状况,是以八个二进制位就可以组合出256种状况,这被称为一个字节(byte)。也就是说,一个字节一共可以用来默示256种不合的状况,每一个状况对应一个符号,就是256个符号,从000000011111111

上个世纪60年代,美国制订了一套字符编码,对英语字符与二进制位之间的关系,做了同一规定。这被称为ASCII码,一向沿用至今。

ASCII码一共规定了128个字符的编码,比如空格“SPACE”32(二进制00100000),大写的字母A65(二进制01000001)。这128个符号(包含32个不克不及打印出来的把握符号),只占用了一个字节的后面7位,最前面的1位同一规定为0

2、非ASCII编码


英语用128个符号编码就够了,然则用来默示其他说话,128个符号是不敷的。比如,在法语中,字母上方有注音符号,它就无法用ASCII码默示。于是,一些欧洲国度就决意,哄骗字节中闲置的最高位编入新的符号。比如,法语中的é的编码为130(二进制10000010)。如许一来,这些欧洲国度应用的编码体系,可以默示最多256个符号。

然则,这里又呈现了新的题目。不合的国度有不合的字母,是以,哪怕它们都应用256个符号的编码体式格式,代表的字母却不一样。比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (?),在俄语编码中又会代表另一个符号。然则不管如何,所有这些编码体式格式中,0—127默示的符号是一样的,不一样的只是128—255的这一段。

至于亚洲国度的文字,应用的符号就更多了,汉字就多达10万阁下。一个字节只能默示256种符号,必然是不敷的,就必须应用多个字节表达一个符号。比如,简体中文常见的编码体式格式是GB2312,应用两个字节默示一个汉字,所以理论上最多可以默示256x256=65536个符号。

中文编码的题目须要专文评论辩论,这篇笔记不涉及。这里只指出,固然都是用多个字节默示一个符号,然则GB类的汉字编码与后文的UnicodeUTF-8是毫无关系的。

3.Unicode


正如上一节所说,世界上存在着多种编码体式格式,同一个二进制数字可以被申明成不合的符号。是以,要想打开一个文本文件,就必须知道它的编码体式格式,不然用错误的编码体式格式解读,就会呈现乱码。为什么电子邮件经常呈现乱码?就是因为发信人和收信人应用的编码体式格式不一样。

可以想象,若是有一种编码,将世界上所有的符号都纳入此中。每一个符号都赐与一个独一无二的编码,那么乱码题目就会消散。这就是Unicode,就像它的名字都默示的,这是一种所有符号的编码。

Unicode当然是一个很大的凑集,如今的范围可以容纳100多万个符号。每个符号的编码都不一样,比如,U+0639默示阿拉伯字母AinU+0041默示英语的大写字母AU+4E25默示汉字。具体的符号对应表,可以查询unicode.org,或者专门的汉字对应表

4. Unicode的题目


须要重视的是,Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应当如何存储。

比如,汉字unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的默示至少须要2个字节。默示其他更大的符号,可能须要3个字节或者4个字节,甚至更多。

这里就有两个严重的题目,第一个题目是,如何才干差别unicodeascii?策画机怎么知道三个字节默示一个符号,而不是分别默示三个符号呢?第二个题目是,我们已经知道,英文字母只用一个字节默示就够了,若是unicode同一规定,每个符号用三个或四个字节默示,那么每个英文字母前都必定有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会是以大出二三倍,这是无法接管的。

它们造成的成果是:1)呈现了unicode的多种存储体式格式,也就是说有很多种不合的二进制格局,可以用来默示unicode2unicode在很长一段时候内无法推广,直到互联网的呈现。

5.UTF-8


互联网的普及,强烈请求呈现一种同一的编码体式格式。UTF-8就是在互联网上应用最广的一种unicode的实现体式格式。其他实现体式格式还包含UTF-16UTF-32,不过在互联网上根蒂根基不消。反复一遍,这里的关系是,UTF-8Unicode的实现体式格式之一。

UTF-8最大的一个特点,就是它是一种变长的编码体式格式。它可以应用1~4个字节默示一个符号,按照不合的符号而变更字节长度。

UTF-8的编码规矩很简单,只有二条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。是以对于英语字母,UTF-8编码和ASCII码是雷同的。

2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有说起的二进制位,全部为这个符号的unicode码。

下表总结了编码规矩,字母x默示可用编码的位。

Unicode符号局限 | UTF-8编码体式格式
十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0 xxxxxxx
0000 0080-0000 07FF | 110 xxxxx 10 xxxxxx
0000 0800-0000 FFFF | 1110 xxxx 10 xxxxxx 10 xxxxxx
0001 0000-0010 FFFF | 11110 xxx 10 xxxxxx 10 xxxxxx 10 xxxxxx

下面,还是以汉字为例,演示如何实现UTF-8编码。

已知unicode4E25100111000100101),按照上表,可以发明4E25处在第三行的局限内(0000 0800-0000 FFFF),是以UTF-8编码须要三个字节,即格局是“1110 xxxx 10 xxxxxx 10 xxxxxx”。然后,从的最后一个二进制位开端,依次从后向前填入格局中的x,多出的位补0。如许就获得了,UTF-8编码是“11100100 10111000 10100101”,转换成十六进制就是E4B8A5

6. UnicodeUTF-8之间的转换


经由过程上一节的例子,可以看到Unicode码是4E25UTF-8编码是E4B8A5,两者是不一样的。它们之间的转换可以经由过程法度实现。

Windows平台下,有一个最简单的转化办法,就是应用内置的记事本小法度Notepad.exe。打开文件后,点击文件菜单中的另存为号令,会跳出一个对话框,在最底部有一个编码的下拉条。


里面有四个选项:ANSIUnicodeUnicode big endian 和 UTF-8

1ANSI是默认的编码体式格式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows简体中文版,若是是繁体中文版会采取Big5码)。

2Unicode编码指的是UCS-2编码体式格式,即直接用两个字节存入字符的Unicode码。这个选项用的little endian格局。

3Unicode big endian编码与上一个选项相对应。我鄙人一节会申明little endianbig endian的涵义。

4UTF-8编码,也就是上一节谈到的编码办法。

选择完编码体式格式后,点击保存按钮,文件的编码体式格式就立即转换好了。

7. Little endianBig endian


上一节已经提到,Unicode码可以采取UCS-2格局直接存储。以汉字为例,Unicode码是4E25,须要用两个字节存储,一个字节是4E,另一个字节是25。存储的时辰,4E在前,25在后,就是Big endian体式格式;25在前,4E在后,就是Little endian体式格式。

这两个古怪的名称来自英国作家斯威夫特的《格列佛纪行》。在该书中,小人国里爆发了内战,战斗原由是人们争辩,吃鸡蛋时毕竟是从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开。为了这件工作,前后爆发了六次战斗,一个皇帝送了命,另一个皇帝丢了王位。

是以,第一个字节在前,就是大头体式格式Big endian),第二个字节在前就是小头体式格式Little endian)。

那么很天然的,就会呈现一个题目:策画机怎么知道某一个文件到底采取哪一种体式格式编码?

Unicode规范中定义,每一个文件的最前面分别参加一个默示编码次序的字符,这个字符的名字叫做零宽度非换行空格ZERO WIDTH NO-BREAK SPACE),用FEFF默示。这正好是两个字节,并且FFFE1

若是一个文本文件的头两个字节是FE FF,就默示该文件采取大头体式格式;若是头两个字节是FF FE,就默示该文件采取小头体式格式。

8. 实例


下面,举一个实例。

打开记事本法度Notepad.exe,新建一个文本文件,内容就是一个字,依次采取ANSIUnicodeUnicode big endian 和 UTF-8编码体式格式保存。

然后,用文本编辑软件UltraEdit十六进制功能,调查该文件的内部编码体式格式。

1ANSI:文件的编码就是两个字节“D1 CF”,这恰是GB2312编码,这也暗示GB2312是采取大头体式格式存储的。

2Unicode:编码是四个字节“FF FE 25 4E”,此中“FF FE”注解是小头体式格式存储,真正的编码是4E25

3Unicode big endian:编码是四个字节“FE FF 4E 25”,此中“FE FF”注解是大头体式格式存储。

4UTF-8:编码是六个字节“EF BB BF E4 B8 A5”,前三个字节“EF BB BF”默示这是UTF-8编码,后三个“E4B8A5”就是的具体编码,它的存储次序与编码次序是一致的。

9. 延长浏览


The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets(关于字符集的最根蒂根基常识)

谈谈Unicode编码

RFC3629UTF-8, a transformation format of ISO 10646(若是实现UTF-8的规定)

(完)


C++的中英文字符串默示(string,wstring)


(畴前面的材料可知,string完全可以存储中文(有效编码只有""\0""=0,其他字符均不为0),然则在显示、字符操纵等方面是无法包管的!)

      在C++中字符串类的string的模板原型是basic_string

template <class _Elem, class traits = char_traits<_Elem>, class _Ax = allocator<_Elem>>
class basic_string{};

      第一个参数_Elem默示类型。第二个参数traits的缺省值应用char_traits类型,定义了类型和字符操纵的函数,如斗劲、等价、分派等。第三个参数_Ax的默认值是allocator类,默示了内存模式,不合的内存布局将操纵指针的不合行动,例如栈、堆或段内存模式等。

     在C++标准里定义了两个字符串stringwstring

typedef basic_string<charstring;
typedef basic_string<wchar_t> wstring;

      前者string是常用类型,可以看作char[],其实这恰是与string定义中的_Elem=char相一致。而wstring,应用的是wchar_t类型,这是宽字符,用于满足非ASCII字符的请求,例如Unicode编码,中文,日文,韩文什么的。对于wchar_t类型,实际上C++中都用与char函数相对应的wchar_t的函数,因为他们都是从同一个模板类似于上方的体式格式定义的。是以也有wcout, wcin, werr等函数。

     实际上string也可以应用中文,然则它将一个汉字写在2char中。而若是将一个汉字看作一个单位wchar_t的话,那么在wstring中就只占用一个单位,其它的非英文文字和编码也是如此。如许才真正的满足字符串操纵的请求,尤其是国际化等工作。

     看一下下面的法度,就会懂得两者的差别。

#include <iostream>
#include <string>
using namespace std;

#define tab "\t"

int main()
{
    locale def;
    cout<<def.name()<<endl;
    locale current = cout.getloc();
    cout<<current.name()<<endl;

    float val=1234.56;
    cout<<val<<endl;

    //chage to french/france
    cout.imbue(locale("chs"));
    current=cout.getloc();
    cout<<current.name()<<endl;
    cout<<val<<endl;

    //上方是申明locale的用法,下面才是本例的内容,因为此顶用到了imbue函数
    cout<<"*********************************"<<endl;

    //为了包管本地化输出(文字/时候/货币等),chs默示中国,wcout必须应用本地化解析编码
    wcout.imbue(std::locale("chs"));

    //string 英文,正确倒置地位,显示第二个字符正确
    string str1("ABCabc");
    string str11(str1.rbegin(),str1.rend());
    cout<<"UK\ts1\t:"<<str1<<tab<<str1[1]<<tab<<str11<<endl;

    //wstring 英文,正确倒置地位,显示第二个字符正确
    wstring str2=L"ABCabc";
    wstring str22(str2.rbegin(),str2.rend());
    wcout<<"UK\tws4\t:"<<str2<<tab<<str2[1]<<tab<<str22<<endl;

    //string 中文,倒置后,变成乱码,第二个字符读取也错误
    string str3("你好么?");
    string str33(str3.rbegin(),str3.rend());
    cout<<"CHN\ts3\t:"<<str3<<tab<<str3[1]<<tab<<str33<<endl;

    //正确的打印第二个字符的办法
    cout<<"CHN\ts3\t:RIGHT\t"<<str3[2]<<str3[3]<<endl;

    //中文,正确倒置地位,显示第二个字符正确
    wstring str4=L"你好么?";
    wstring str44(str4.rbegin(),str4.rend());
    wcout<<"CHN\tws4\t:"<<str4<<tab<<str4[1]<<tab<<str44<<endl;

    wstring str5(str1.begin(),str1.end());//只有char类型的string时才可以如此机关
    wstring str55(str5.rbegin(),str5.rend());
    wcout<<"CHN\tws5\t:"<<str5<<tab<<str5[1]<<tab<<str55<<endl;

    wstring str6(str3.begin(),str3.end());//如此机关将失败!!!!
    wstring str66(str6.rbegin(),str6.rend());
    wcout<<"CHN\tws6\t:"<<str6<<tab<<str6[1]<<tab<<str66<<endl;

    return 0;
}


 成果如下:(略)


     上方显示了本地化的感化,是在数字中每三位加一个逗号,其实对时候/文字等都是用影响的。

     下面的输出说了然,如何正确应用stringwstring的办法。第三个因为应用string来默示汉字,呈现了一些错误。最后一行也是错误,导致了输出也受到了影响,没有空格与回车。(最后两个就不要管中英文了,仅仅申明一下中文机关办法是错误的)

     《把握标准C++类》在第十二章《说话支撑》中专门讲C++的国际化和本地化题目,C++供给了I18N的标准处理惩罚,软件开辟者可以参考。

       C++标准库还是很是博大高深的,功能斗劲齐备的。持续进修。

摘自: http://www.cnblogs.com/xiaoyz/archive/2008/10/11/1308860.html








作者:zhenjing.chen


出处:http://www.cnblogs.com/zhenjing/

未注明转载的文章,版权归作者所有,迎接转载,但未经作者赞成必须保存此段声明,且在文章页面明显地位给出原文连接,不然保存究查法令义务的权力。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值