概述
做通讯的时侯,或则使用IO流读写数据的时侯耳朵总是晕昏沉的。与计算机打交道久了,不可防止会听到“鬼念咒”式的乱码,让人云里雾里的,非常可恶。
本文将介绍为何会出现乱码,以及字节、字符、字符集和编码之间的关系。
为何会出现乱码?
乱码出现的缘由主要有以下几个:
锟斤拷形成的诱因详见文末
类似下边这些编码和解码的“字符集”不同造成的混乱:
兵乓球拍卖完了(兵乓球拍这个商品收摊了/兵乓球在拍卖会上拍卖完了)我要煮猪肉(我要煮过的猪肉/我要把猪肉煮了)A国对B国的逼抢早有打算(A国早已打算好逼抢B国了/A国早已做好打算应对B的逼抢)他舅舅原先在广州一所不错的学校里当物理班主任(他祖父之前是老师,如今可能不是/原先这么,他祖父是一个老师)砍死了猎人的狗(猎人被压死了/狗被压死了)热爱人民的首相(一位热爱人民的首相/我们都热爱人民的首相)去年好霉气少不得打官司猪儿大似象老鼠死干净(去年好,霉气少,不得打官司,猪儿大似象,老鼠死干净/去年好霉气,少不得打官司,猪儿大似象老鼠,死干净。)单号给我核查(只要单号为质数的单子/查单子的号码)他爬过山没有?(有没有翻过这座山/有没有攀越山的经历)他的故事讲不完(他晓得的故事多/关于他的故事讲不完)砍死了猎人的狗(狗压死了猎人/猎人的狗被压死了)
为了防止乱码问题,须要确保文本的字符集与程序所使用的字符集一致,但是在文本传输或处理过程中,要正确地处理编码方法。据悉,还须要注意文本的格式正确性,以及程序的正确性。
为何要编码?
字符必须编码后才会被计算机处理。在计算机中所有的数据,在储存和运算时,都要用二补码数表示。
不晓得你们有没有想过一个问题,那就是为何要编码?我们能不能不编码?要回答这个问题必需要回到计算机是怎样表示我们人类才能理解的符号的,这种符号也就是我们人类使用的语言。计算机只能处理二补码数据,须要将文字或符号转换为二补码方式进行处理。因为人类的语言太多,因此表示这种语言的符号太多,难以用计算机中一个基本的储存单元——Byte来表示,因此必需要经过分拆或一些“翻译/转换”工作,能够让计算机能理解。目前计算机领域中广泛使用的是只有0和1的二补码语言,只能表示和储存二补码的数据,其它任何语言要才能在计算机中使用必须经过一次“翻译/转换”,把它“翻译/转换”成0和1的组合。这个“翻译/转换”的过程就是编码。编码可以实现文字或符号在计算机系统中传输和储存。
所以总的来说,编码的缘由可以总结为:
计算机中储存信息的最小单元是一个字节/Byte即8个bit,所以能表示的字符范围是0~255个人类要表示的符号太多,难以用一个字节/Byte来完全表示要解决这个矛盾计算机中须要一个新的数据结构char,要实现从char到Byte的互相转换则必须编码
字符是如何编码的?
编码(Encoding):信息从一种方式或格式转换为另一种方式或格式的过程。解码(Decoding):是编码的逆过程。如同查字典一样。
以ASCII字符集为例来谈谈字符是如何编码的:
上图中的术语解释:
字符
字符(Character)指人类使用的文字或符号的统称,包括文字符号、图形符号、数学符号、字母、运算符号、标点符号和其他符号,以及一些功能性符号。可以由一个或多个字节表示。通常来说我们称某个字符集上面的字符,叫xx字符,如ASCII字符集上面的ASCII字符,GB2312字符集上面的GB2312字符。
字符集
字符集(CharacterSet、Charset),一组字符的集合。每位字符在一个字符集中都有一个惟一的编码值(码点)。字符集经常和一种具体的语言文字对应上去,该文字中的所有字符或则大部份常用字符就构成了该文字的字符集,例如英语字符集。一组有共同特点的字符也可以组成字符集,例如简体汉字字符集、日文汉字字符集。字符集的子集也是字符集。字符集一般拿来框定一个范围。包含那些字符就早已够了,可以满足日常使用了。
常见字符集:ASCII字符集、GB2312字符集、BIG5字符集、GBK字符集、GB18030字符集、Unicode字符集等。
码位
在字符编码术语中,又叫码点(CodePoint)、编码位置,是一个字符集编码表为每一个字符分配一个惟一的数字ID。诸如,ASCII码包含128个码位,范围是016补码到7F16补码,扩充ASCII码包含256个码位,范围是016补码到FF16补码,而Unicode包含1,114,112个码位,范围是016补码到10FFFF16补码。
相同的码点在不同的字符集中映射的字符不一定是相同的。这也是乱码的直接诱因。
字符编码
字符编码(CharacterEncoding)规定每位“字符”分别用一个字节还是多个字节储存,用什么字节来储存,是把字符集中的字符按一定形式转换/翻译为一个指定集合中的某一对象的规则。外部程序通过这些编码就可以从字符集文件中调用指定的字符。我们常见的计算机字体文件就使用了字符集编码,通过输入法输入文字或则浏览网页时就会通过指定的字符集编码从字体文件中调用字符。例如将字符编码为由0和1两个数字所组成的位串模式、由0~9十个数字所组成的自然数序列或电脉冲等,借以在字符集与指定集合二者之间构建一个对应关系(即映射关系)的过程。这是信息处理的一项基础技术。常见的反例包括将拉丁字母表编码成摩斯电码和ASCII码。
字符游行影响字符编码。例如汉字有8万多个,肯定没法使用ASCII的单字节编码,由于ASCII能抒发的字符太少,放不下这么多汉字。
各个国家和地区在制定员码标准的时侯,“字符集”和“编码”一般都是同时制订的。
比特(bit):也可称为“位”,是计算机中最小的储存单位,是binarydigit(二补码数位)的简写linux 安装gbk字符集,指二补码中的一位。
字节(Octet/Byte):计算机中信息计量的一种单位,一个位就代表“0”或“1”,每8个位(bit)组成一个字节(Octet/Byte)。
GBK一个英文字符编码时会使用两个字节的方式储存GBK规定:汉字的第一个字节的第一位必须是1
为何要有字符集?
不同国家或民族的文字或符号要在计算机中储存和展示,就须要先让计算机能理解。人类要表示的符号太多,假如要让计算机能理解所有的符号,工作量太多,且不是必要的。曾经设计的时侯,谁晓得计算机会如此普及呢?例如你要看一本中文的书,要不要把英语一块学了,之后再这本英文书?这些在项目管理的角度看这些做法是“镀金”,在老总看来就称作“脱裤子打屁”,由于只用学会英语就早已够了。
科研人员在交付系统时只须要确保计算机能理解和抒发特定范围内的字符就可以了。这个范围内字符的集合就是字符集。
为何会有如此多字符集?搞一个不就行了吗?
制订字符集是有成本的,出现如此多字符集是有历史缘由的。目前的万国码(Unicode编码标准)早已包含了世界上所有的文字、符号、数字、标点等字符。
我们从不同字符集诞生的历程来瞧瞧为何会有如此多不同的字符集:
假如计算机仍然只有日本人使用的话,没有问题。
然而后来当一些亚洲国家也开始使用计算机的时侯,例如美国、德国。她们会发觉,我们国家里的字符不在你这128个字符中。
于是法德两国在原有ASCII码的基础上进行了扩充。把原先的第一位0弄成了1,也就是从128个字符扩充到了256个字符,即又新增了128个。在ASCII字符集基础上包含了新增128个字符的字符集就称作扩充ASCII字符集或ISO-8859-1字符集或Latin-1。
这个办法,解决了一些欧澳洲家的字符编码问题。
此时,在中国要想使用计算机,是不是也要对用到的字符进行编码。
这样看来,是不是每位国家都可以设计一套属于自己国家的编码:
随着计算机技术发展迅速,各国之间的信息交流也越来越频繁,而且不同国家、不同语言之间的文字编码标准却各不相同,这给信息交流带来了很大的困难。为了解决这个问题,Unicode联盟创立了,开始拟定Unicode编码标准,并不断建立和更新。目前,Unicode编码标准已然成为了世界上最广泛使用的文字编码标准之一,它可以支持超过13万种字符,包括世界上所有的主要文字系统。
万国码(Unicode编码标准)是一种用于表示文字的编码标准,它可以将世界上所有的文字、符号、数字、标点等字符都编码成数字,便于计算机就能辨识和处理。
Unicode编码标准是一种国际标准,它由国际组织Unicode联盟拟定,目的是为了解决不同国家、不同语言之间的文字编码问题。
英文编码的发展历程
ASCII
ASCII(AmericanStandardCodeforInformationInterchange)日本标准信息交换码,是第一个标准字符集和编码。ASCII字符集迄今为止共收录了128个字符,包含了基本的拉丁字母(英语字母)、阿拉伯数字(也就是1234567890)、标点符号(,.!等)、特殊符号(@#$%^&等)以及一些具有控制功能的字符(常常不会显示下来)。ASCII首次发布于1963年,并于1967年成为英国国家标准,后经数次修订,1986年定型最终版本使用至今。后被ISO(InternationalStandardizationOrganization)国际标准化组织定为国际标准ISO/IEC646。ASCII码对照表是世界最通用的信息交换标准。
ASCII使用用一个字节(8bits)进行编码arch linux,属于单字节编码。因而最多只能表示256个字符。基础的ASCII使用7bits编码,最低位位为0,或则用于奇偶校准。ASCII编码适用于所有的拉丁字母。
ASCII既可以指ASCII字符集,也可以指ASCII编码。
后来,因为各粤语言的加入,ASCII早已不能满足信息交流的须要,因而,为了才能表示其它国家的文字,各国在ASCII的基础上制订了自己的字符集,这种从ANSI标准派生的字符集被习惯的合称为ANSI字符集,它们即将的名称应当是MBCS(Multi-ByteChactacterSystem,即多字节字符系统)。这种派生字符集的特征是以ASCII127bits为基础,兼容ASCII。
GB2312
GB2312全称《信息交换用汉字编码字符集——基本集》,是中国最早的英文字符集,属于双字节字符集(DBCS)。也是中华人民共和国国家汉字信息交换用编码linux运维博客,使用2个字节表示英文字符,属于双字节编码。于1980年由国家标准总局发布。
GBK既可以指GBK字符集,也可以指GBK编码。
GB2312字符集只收录了6763个汉字,因而许多原先极少使用的冷僻字没有收录,如今这种字其实显得流行了,比如:朱镕基的“镕”字,未收入GB2312-80,如今台湾的报业停刊只好使用(金+容)、(金容)、(左金右容)等来表示,方式不一而同,这促使表示、存储、输入、处理都十分不便捷。
Big5
Big5是用于简体英文的字符集,属于双字节字符集(DBCS)。采用2个字节表示英文字符,属于双字节编码。于1984年发布。
ISO8859-1
ISO8859-1字符集,也就是Latin-1,是欧洲常用字符,包括德法两国的字母,是国际标准化组织(ISO)认可的8位字符集。于1987年发布。ISO-8859-1一直是单字节编码,它总共能表示256个字符。向上兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致。
ISO-8859-1字符集应用最广泛。由于ISO-8859-1编码范围使用了单字节内的所有空间,在支持ISO-8859-1的系统中传输和储存其他任何编码的字节流都不会被抛弃。这是一个很重要的特点。换言之,把其他任何编码的字节流当成ISO-8859-1编码看待都没有问题。ISO8859-1是HTML4.01中的默认字符。
Unicode
Unicode是一种全球字符集,支持几乎所有的字符,它将世界各类语言的每位字符定义一个惟一的编码,以满足跨语言、跨平台的文本信息转换。于1991年发布。Unicode是由国际组织设计,是一个可以容纳全世界所有语言文字的字符集。Unicode的学名是“UniversalMultiple-OctetCodedCharacterSet”,简称为UCS。UCS可以看作是“UnicodeCharacterSet”的简写。
Unicode指Unicode字符集。Unicode的编码有多种实现方法,例如UTF-8编码、UTF-16编码、UTF-32编码等
GBK
GBK(ChineseInternalCodeSpecification)是GB2312的扩充,属于双字节字符集(DBCS)。支持更多的英文字符。于1995年发布。该编码标准兼容GB2312,即同一个字符在这种方案中总是有相同的编码,共收录汉字21003个、符号883个,并提供1894个造字码位,简、繁体字融于一库。包括了GB2312中的全部汉字、非汉字符号、BIG5中的全部汉字、其它汉字、部首、符号,共计984个。
GBK既可以指GBK字符集,也可以指GBK编码。
GB18030
GB18030字符集是最新的汉字编码字符集国家标准,向上兼容GBK和GB2312标准,即同一个字符在这种方案中总是有相同的编码,是GBK的升级版,支持更多的英文字符和国际字符。于2000年发布。采用单字节、双字节和四字节三种形式对字符编码。
GB18030既可以指GB18030字符集,也可以指GB18030编码。
最新的英文字符集是Unicode的一部份,可以使用UTF-8编码进行表示。
小结
本文以乱码为切入口,梳理了微机原理中字符的编码、字符集相关知识。我们了解到编码是将人类文明系统中的文字或符号映射到计算机的二补码系统的过程,只有经过编码才能让计算机就能辨识和处理,将人类世界的符号系统与计算机系统打通,而字符集定义了字符和编码值之间的映射关系。了解这种概念可以帮助我们更好地理解和解决乱码问题。
加油站
1、锟斤拷——锟(0xEFBF),斤(0xBDEF),拷(0xBFBD)
这个问题是在初期的Unicode版本中存在的,后续的Unicode版本对这个问题进行了修补。目前的Unicode版本早已没有这个问题,可以正确地表示所有字符。
之前在搜索引擎和网站上常常看见这三个有点不正经的字符。这个乱码形成的缘由是GBK字符集和Unicode字符集之间的转换出了问题。Unicode和老编码体系的转化过程中,肯定有一些字,用Unicode是无法表示的,Unicode官方用了一个占位符来表示这种文字,这就是:U+FFFDREPLACEMENTCHARACTER。这么U+FFFD的UTF-8编码下来,正好是'xefxbfxbd'。假如这个'xefxbfxbd',重复多次,比如'xefxbfxbdxefxbfxbd',之后根据GBK/CP936/GB2312/GB18030的的编码规则,一个汉字2个字节,最终的结果就是:锟斤拷——锟(0xEFBF),斤(0xBDEF),拷(0xBFBD)。
后来的Unicode版本通过不断更新和扩充字符集来修补这个问题。Unicode不断地添加新的字符,以覆盖各类语言和符号系统中的所有字符。通过这些方法,Unicode才能正确地表示所有的字符,包括之前未能表示的字符。
Unicode的修补过程主要包括以下几个方面:
添加新的字符:Unicode不断地添加新的字符,以覆盖各类语言和符号系统中的所有字符。这样,起初难以表示的字符就可以通过新添加的字符来表示了。扩充编码空间:Unicode通过扩充编码空间来容纳更多的字符。最初的Unicode版本使用16位编码,可以表示65536个字符。后来,Unicode扩充到了21位编码linux 安装gbk字符集,可以表示超过100万个字符。规范化处理:Unicode还引入了规范化处理的概念,用于处理字符的等价性和兼容性。规范化处理可以将不同的字符序列转换为统一的规范方式,因而避开了字符转换过程中的乱码问题。
通过以上的修补举措,现今的Unicode版本早已才能正确地表示所有的字符,解决了之前存在的乱码问题。
2、Octet和Byte
在读RFC或网路设备文档时,常常看到Octet这量词来指代8位(bit),为什么不用Byte呢?有啥区别?
Octet总是抒发8个bit(如同他名子所说的),当我们在谈论网路上的问题时,更喜欢使用这个词而不是Byte。
Byte一般情况下也表示8个bit,然而确切的说,Byte表示的是CPU可以独立的轮询的最小显存单位(不过通过移位和逻辑运算,CPU也可以轮询到某一个单独的bit)。曾几何时,有些笔记本的轮询单位不是8Bit的。而如今,大多数情况下byte可以和octet等价而且假如你想要指出确切的8bit时,你就应当使用octet而不是byte。
另外,还有一个量词nibble拿来形容一个字节的一半(一般是4bit)不过这个词基本上没人用就是了。
#从外边打开是食物,从上面打开的是生命#
引用
英文有什么容易让人形成歧义的成语或说法?
英文有什么容易让人形成歧义的成语或说法?
字符编码的前世此生
HTMLISO-8859-1参考指南
字符编码笔记:ASCII,ANSI,GBK、ISO-8859-1,Unicode、UTF-8
字符、字符集、字符编码的基础知识科普
汉字字符集编码查询
GBK编码表
十分详尽的字符编码讲解,ASCII、GB2312、GBK、Unicode、UTF-8等知识点都有
一听就懂字符集、ASCII、GBK、UTF-8、Unicode、乱码、字符编码、解码问题的讲解
13-ASCII码-动漫