首页 > 其他分享 >计算机字符编码的前世今生

计算机字符编码的前世今生

时间:2023-04-04 21:32:07浏览次数:40  
标签:编码 今生 UTF 字节 字符 前世 BOM ASCII


一、前言

有人丢给你下面这张图,如果你能清楚地说明它们之间的关系以及用途,那么你对字符编码的理解肯定过关了。

计算机字符编码的前世今生_ascii码表

不知道看了上面这张图,是否有混乱的感觉,本文试着给你梳理、讲透这些孤立的几个单词之间联系…

二、关于字符编码,你所需要知道的

2.1 ASCII(寡头垄断时期)

计算机内部,所有信息最终都是一个二进制值。每一个二进制位(bit)有0和1两种状态,8个二进制位称之为1个字节。把键盘上(如下图)所有按键的状态。

计算机字符编码的前世今生_编码器_02

用8位二进制共256种表示绰绰有余。把所有的空格、标点符号、数字、大小写字母分别用连续的字节状态表示,一直编到了第127号,这样计算机利用8位二进制位(1个字节)就可以用来存储英语的文字了,这就是大名鼎鼎的ASCII(美国信息互换标准代码)。当时世界上所有的计算机都用同样的ASCII方案来保存英文文字。

2.2 非 ASCII 编码(汉字编码的发展)

伴随着互联网的兴起,计算机技术的发展,世界各地都开始使用计算机,但是很多国家用的不是英文,所适用的字母里有许多是ASCII里没有的。

为了可以在计算机保存他们的文字,决定采用 127号之后的空位来表示这些新的字母、符号,还加入了很多画表格时需要用下到的横线、竖线、交叉等形状,一直把序号编到了最后一个状态255。

从128 到255这一页的字符集被称“扩展字符集”。此之后,贪婪的人类再没有新的状态可以用了。

计算机字符编码的前世今生_ascii码表_03

随着计算机在中国流行时,已经没有可以利用的字节状态来表示汉字,况且有6000多个常用汉字需要保存。但这难不倒智慧的中国人民,我们就把那些127号之后的奇异符号们直接取消掉,并规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。

在这些编码里,我们还把数学符号、罗马希腊的字母都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的”全角”字符。而原来在127号以下的那些就叫”半角”字符了。中国人民看到这样很不错,于是就把这种汉字方案叫做 “GB2312”。GB2312 是对 ASCII 的中文扩展。

计算机字符编码的前世今生_utf_04

(图片来源于网络)

但是中国的汉字太多了,我们很快就就发现有许多人的人名没有办法在这里打出来。我们不得不继续把GB2312 没有用到的码位找出来老实不客气地用上。后来还是不够用,于是干脆不再要求低字节一定是127号之后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。

结果扩展之后的编码方案被称为 GBK 标准,GBK包括了**GB2312 **的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。后来少数民族也要用电脑了,于是我们再扩展,又加了几千个新的少数民族的字,GBK扩成了 GB18030

2.3 非 ASCII 编码

百花齐放,各自编码标准带来的问题

当时各个国家都像中国这样搞出一套自己的编码标准,结果互相之间谁也不懂谁的编码,谁也不支持别人的编码,就连大陆和台湾这样只相隔了150海里,使用着同一种语言,也分别采用了不同的 DBCS 编码方案。

当时的中国人想让电脑显示汉字,就必须装上一个“汉字系统”,专门用来处理汉字的显示、输入的问题,像是那个台湾的愚昧封建人士写的算命程序就必须加装另一套支持 BIG5。

编码的什么“倚天汉字系统”才可以用,装错了字符系统,显示就会乱了套!这怎么办?

而且世界民族之林中还有那些一时用不上电脑的穷苦人民,他们的文字又怎么办?

计算机字符编码的前世今生_unicode_05

(图片来源于维基百科)

2.4 Unicode

世界这么乱,得我来管管,大一统时期

ISO(国际标谁化组织)的国际组织决定着手解决这个问题。采用的方法很简单:废了所有的地区性编码方案,重新搞一个包括了地球上所有文化、所有字母和符号的编码!

他们打算叫它“Universal Multiple-Octet Coded Character Set”,简称UCS, 俗称 “Unicode”。Unicode相当于一个抽象层,给每个字符一个唯一的码点(code point)

用 0x000000 - 0x10FFFF 这么多的数字去对应全世界所有的语言、公式、符号。然后把这些数字分成 17 部分,把常用的放到 0x0000 - 0xFFFF,也就是 2 个字节,叫做基本平面 (BMP);从 0x010000 - 0x10FFFF 再划分为其他平面。

计算机字符编码的前世今生_ascii码表_06

(图片来源于维基百科)

栗子:「v维」

计算机字符编码的前世今生_编码器_07

如果 「v维」 这个字符串放到内存中就是 0x767ef4。问题来了,计算机怎么知道,几个字节代表一个字符呢?是 0x76呢?还是 0x7ef4 呢?还是 0x767ef4?

Unicode只是对信源编码,对字符集数字化,解决了字符到数字化的映射。接下来面临如何解决存储和传输的问题。

三、传输和存储

用通信理论的思路可以理解为:

Unicode是信源编码,对字符集数字化;

UTF-32、UTF-16、UTF-8是信道编码,为更好的存储和传输。

3.1 UTF-32

UTF-32 编码,简单明了,码点值是多少,内存中就存多少,UTF-32 缺点很明显了,字母 A 原本只需要 1 个字节去存储,而现在却用了 4 个字节去存,大部分位置都是 0。

提问:我们为什么要多存那么多零呢?

计算机字符编码的前世今生_ascii码表_08

3.2 UTF-16

问题「亮」 码点值是 20142,换成 16 进制就是 0x4eae,内存中是按字节进行编址的。所以我们是先存4e呢?还是ae?

一个 Unicode 的码点值会对应一个数字,对于Basic平面的字符,我们直接把这个数字存到内存中。

计算机字符编码的前世今生_unicode_09

UTF - 16 编码的时候,除本身的字节,为了区分大端序和小端序,最开头还多了两个字节,ff和fe。feff代表大端序,fffe代表小端序。

计算机字符编码的前世今生_ico_10

(Notepad中的BOM)

小知识:feff和fffe也叫做 BOM,它可以区分不同编码。UTF-16 编码最小单位是两个字节,所以有字节序的问题,从而加了 BOM 来区分是大端序还是小端序。

3.3 UTF-8

UTF-8 顾名思义,是一套以 8 位为一个编码单位的可变长编码。会将一个码位编码为 1 到 4 个字节。一个码点值会生成 1 个或多个字节,然后把这些字节按顺序存就可以了。

小知识:UTF-8 无 BOM 或者 UTF-8 BOM。UTF - 8 的 BOM 是 EF BB BF ,UTF-8 并不存在字节序的问题,因为它的最小编码单位就是字节。

UTF-8 并不需要区分大端序还是小端序,所以可以不需要 BOM。如果加了 BOM,对于一些读取操作,它可能会把读取到的 BOM 认为是字符,从而造成一些错误。所以我们保存 UTF - 8 编码的文件时,最好选择无 BOM。

计算机字符编码的前世今生_ico_11

栗子:「知」

计算机字符编码的前世今生_utf_12

根据上表中的编码规则,「知」字的码位 U+77E5 属于第三行的范围:

计算机字符编码的前世今生_ascii码表_13

这就是将U+77E5 按照 UTF-8 编码为字节序列E79FA5 的过程,反之亦然。

计算机字符编码的前世今生_ascii码表_14

3.4 ANSI

「ANSI」指的是对应当前系统 locale 的遗留(legacy)编码。

计算机字符编码的前世今生_ico_15

Windows 里说的「ANSI」其实是 Windows code pages,这个模式根据当前 locale 选定具体的编码,比如简中 locale 下是 GBK。把自己这些 code page 称作「ANSI」是 Windows 的臭毛病。在 ASCII 范围内它们应该是和 ASCII 一致的。

3.1 扩展思考

问:在java中char 型变量中能不能存贮一个中文汉字,为什么?

答:java中使用的编码符号集是Unicode(不涉及特定的编码方式,给每个符号分配一个二进制编码,目前已容纳容纳100多万个符号),而汉字已纳入Unicode字符集, 而char类型占两个字节,用来表示Unicode编码,所以是可以存储汉字的

问:tomcat的中默认ISO-8859-1编码,如何解决web项目中的乱码问题?

答:

**方式一:**修改tomcat下的conf/server.xml文件

<Connector port="8080"  protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8 useBodyEncodingForURI="true"/>
  • URIEncoding=”UTF-8“:即可让Tomcat(默认ISO-8859-1编码)以UTF-8的编码处理请求参数。
  • useBodyEncodingForURI=“true”:是指请求参数的编码方式采用请求体的编码方式。

**方式二: **

1)当使用字符流向浏览器发送页面信息时,默认查询的是ISO-8859-1码表

  • 设置1:response.setCharacterEncoding(“UTF-8”)
  • 设置2:response.setContentType(“text/html;charset=UTF-8”)

2)客户端请求服务器出现的中文乱码解决方式

  • POST请求方式:浏览器当前使用什么编码,表单提交的参数就是什么编码,
    服务端处理:
    request.setCharacterEncoding(“utf-8”)。
  • GET请求方式:
String name=request.getParameter("name");//首先拿到参数的值

//得到的byte[] 再重新用utf-8去编码,即可得到正常的值

name=new String(name.getBytes("iso-8859-1")/**用参数的值用iso-8859-1来解码**/,"utf-8");String name=request.getParameter("name");//首先拿到参数的值//得到的byte[] 再重新用utf-8去编码,即可得到正常的值name=new String(name.getBytes("iso-8859-1")/**用参数的值用iso-8859-1来解码**/,"utf-8");

说明:tomcat的 j2ee实现对表单提交即 post方式提示时处理参数采用缺省的 iso-8859-1来处理,tomcat对 get方式提交的请求对 query-string 处理时采用了和 post方法不一样的处理方式。

四、总结

回到前言中的那个问题,整理了下面这张图,不知现在的你是否对字符编码有了更清楚的认识…

用通信理论的思路可以理解为:

Unicode是信源编码,对字符集数字化;

UTF-32、UTF-16、UTF-8是信道编码,为更好的存储和传输。

计算机字符编码的前世今生_编码器_16

参考资料

1、《深入理解计算机系统》

作者:vivo互联网服务器团队-Zhu Wenjin


标签:编码,今生,UTF,字节,字符,前世,BOM,ASCII
From: https://blog.51cto.com/u_14291117/6169681

相关文章

  • mp4v2再学习 -- H264视频编码成MP4文件
    一、H264视频编码成MP4文件参看:H264视频编码成MP4文件参看:mp4v2在VS2010下的编译与在项目中的使用最近做项目需要将H264文件封装为mp4文件,从网上找到了MP4V2库,下载下来后不知道从何下手,官方网站https://code.google.com/p/mp4v2/在windows下的编译过程介绍的很简短,对刚刚开始使用VS......
  • LiveGBS流媒体平台国标GB/T28181在国标级联上级时如果设备是H265视频编码上级只支持H2
    @目录1、什么是GB/T28181级联2、获取上级接入配置信息2.1、接入第三方国标平台2.2、接入LiveGBS示例3、配置国标级联3.1、国标级联菜单3.2、添加上级平台3.3、编辑上级平台级联3.4、共享通道给上级平台(选择通道)3.5、共享通道给上级平台(分组共享)3.6、推送通道4、强制推送H264编码5......
  • sql 单号编码规则
    --SETQUOTED_IDENTIFIERON|OFF--SETANSI_NULLSON|OFF--GO/*Description:单号编码规则@key:开头字符串@datelen:日期长度2:年的后两位4:年6:年月8:年月日@numlen:流水号长度例如0:14:0001@spacer:默认空*/ALTERPROCPro_realtime_GetMaxBillNo(@keyNVARCH......
  • 逆向——字符与字符串,中文字符GB2312编码由来
    字符与字符串在之前的课程中我们了解到变量的定义决定两个事情,第一是决定存储的数据宽度,第二是决定了存储的数据格式,那么我们来看下下面的代码:inta=123;//变量x,数据宽度为4个字节,里面存储的是补码(在计算机系统中,数值一律用补码来存储)intfloatb=123.4F;//IEEE编码(......
  • [oeasy]python0123_中文字符_文字编码_gb2312_激光照排技术_王选
    中文编码GB2312回忆上次内容上次回顾了日韩各有编码格式日本有假名五十音一字节可以勉强放下 有日本汉字字符数量超过20000+  韩国有谚文数量超过500一个字节放不下 有朝鲜汉字字符数量超过20000+......
  • 字符编码介绍
    字符编码是用于将字符集中的字符转换为二进制数据的方式。以下是常见的字符编码:ASCII编码:AmericanStandardCodeforInformationInterchange(美国信息交换标准代码),它使用7位二进制数来表示128个字符,ASCII编码最早用于电报通信,包括大小写字母、数字和一些特殊字符。ASCII编码......
  • 每日总结--2023/3/29(解决sevlet报错问题和数据库中文编码错误)
    今日完成:昨天的残留问题,查询了很多资料,也没能完全解决。首先是tomcat版本问题,重新下载并且部署了tomcat10版本的内容,解决了sevlet代码报错的问题。但是连接数据库仍然是不成功,报500错误,检查了mysql数据库,发现数据库正常(除中文变为?的bug)。连接数据库暂时仍不成功,但是成功解决......
  • 4·2HTTP协议中的编码和解码、4·3协议之基本认证、4·4中长连接与短连接、4·5中介之
     。。Http协议中的编码和解码YRL的编码与解码%编码规范对URL中属于ASCII字符集的非保证留字不做编码;对URII中的保留字需要取其ASXII内码,然后加上%前缀将该字符进行编码;对于URL中的非ASCII字符需要取其Unicode内码然后加上%前缀将该字......
  • 我如何回答编码面试问题的框架
    我讨厌编码面试已经不是什么秘密了。他们是一种糟糕的招聘方式并且容易出现误报(也就是不必要地拒绝优秀候选人)。对于大多数公司来说,提出白板式的问题并不符合他们的最大利益。不幸的是,它们是行业标准。作为一名软件工程师,您必须在求职过程中回答白板上的问题。所以,这是我如何擅......
  • sublime编辑器中ANSI编码的汉字出现乱码
    问题:使用sublime打开一个ANSI编码的文件,出现乱码。解决方法:安装ConvertToUTF8插件打开sublime,按键Ctrl+Shift+p ,会出现如下图所示 然后,你输入installpackage点击InstallPackage,然后,你再输入ConvertToUTF8点击回车.这时,你可以在sublime的左下角看见提示,这说明正在安装C......