文字显示 —— 字符编码

本文讲述了字符编码的发展历程,从ASCII的局限性到ANSI的扩展,以及Unicode的统一解决方案,特别是UTF-8在处理多语言字符和防止乱码方面的重要性。

文字显示

计算机可以显示不同的字符,字符又可以选择以不同的字体样式显示

image-20240408192028761 image-20240408192038238

字符编码决定决定显示何种字符

字体文件决定字符以何种形态显示

字符编码

ASCII

由于只定义了128个字符,所以用一个字节来表示一个字符(0~127)

ascii字符编码的最高位永远是0

image-20240408192112171

ANSI

话说计算机是由美国佬搞出来的嘛,他们觉得一个字节(可以表示256个编码)表示英语世界里所有的字母、数字和常用特殊符号已经绰绰有余了(其实ASCII只用了前127个编码)。后来欧洲人不干了,法国人说:我需要在小写字母加上变音符号(如:é),德国人说:我也要加几个字母(Ä ä、Ö ö、Ü ü、ß)。于是,欧洲人就将ASCII没用完的编码(128-255)为自己特有的符号编码(后来称之为“扩展字符集”)。等到我们中国人开始使用计算机的时候,尼玛,256个编码哪够?我泱泱大中华,汉字起码也得N多万吧,就连小学生都得要求掌握两三千字。国标局最后拍板:一个字节不够,那我们就用多个字节来为汉字编码吧,但是,国情那么穷,字节那么贵,三个字节伤不起,那就用俩字节吧,先给常用的几千汉字编个码,等以后国家强盛了人民富裕了,咱再扩展呗—于是GB2312就产生了。台湾同胞一看,尼玛,全是简体字,还让不让我们写繁体字的活了,于是台湾同胞也自己弄了个繁体字编码—大五码(Big-5)。同时,其它国家也在为自己的文字编码。最后,微软苦逼了:顾客就是上帝啊,你们的编码我都得满足啊,这样吧,卖给美国国内的系统默认就用ASCII编码吧,卖给中国人的系统默认就用GBK编码吧,卖给韩国人的系统默认就用EUC-KR编码,…但是为了避免你们误会我卖给你们的系统功能有差异,我就统一把你们的默认编码都显示成ANSI吧。—本故事纯属虚构,但“ANSI编码”确实只存在于Windows系统。

ASNI 是 ASCII 的扩展,向下包含 ASCII。**对于 ASCII 字符仍以一个字节来表示,对于非 ASCII 字符则使用 2 字节来表示(并且这两个字节的首位都为1)。**并没有固定的 ASNI 编码,它跟“本地化”(locale)密切相关。比如在中国大陆地区,ANSI 的默认编码是GB2312;在港澳台地区默认编码是 BIG5。以数值“0xd0d6”为例,对于 GB2312 编码它表示“中”;对于 BIG5 编码它表示“笢”。所以对于 ANSI 编码的 TXT 文件,如果你打开它发现乱码,那么还得再次细分它的具体编码。

对于一个txt文件,里面的编码数值如下

image-20240408192836501

选择不同的编码(或者为字符集)显示的字符是不同的

image-20240408193200510

这仅仅是在中国地区就出现这些不兼容的问题。对于不同国家,它们默认的ANSI 编码各不相同,所以同一个 TXT 文件在不同国家就很有可能出现乱码。

根本的原理在于没有“统一的编码”,那解决方法自然就是使用“统一的编码”:UNICODE。

UNICODE

使用unicode编码就是为了解决ansi编码所遗留的问题(相同的编码值在不同的国家或地区显示不同的字符 eg:数值“0xd6d0”,对于GB2312 编码它表示“中”;对于 BIG5 编码它表示“笢”)

unicode编码:对于地球上任意一个字符,都给它一个唯一的数值。

UNICODE 仍然向下兼容 ASCII,但是对于其他字符会有对应的数值,比如对于“中”、“笢”,它们的数值分别是:0x4e2d、0x7b22

UNICODE的编码实现

所谓的编码实现就是对于一个数值,你怎么去表示它

对于 “中” 而言,直接写入编码值0x4e2d吗?不行,因为0x4e、0x2d在ascii编码中代表着别的字符,如何让计算机知道这是一个整体,是需要一定技巧的,也就是编码实现

1

使用3个字节来表示1个unicode

不行,太浪费了

2

使用两个字节来表示1个unicode

UTF-16 LE

Little endian 表示小字节序,数值中权重低的字节放在前面,比如字符“A 中”在 TXT 文件中的数值如下,其中的“A”使用“0x41 0x00”两字节表示;“中”使用“0x2d 0x4e”两字节表示。文件开头的“0xff 0xfe”表示“UTF-16 LE”。

image-20240408195041326
UTF-16 BE

Big endian 表示大字节序,数值中权重低的字节放在后面,比如字符“ab中”在 TXT 文件中的数值如下,其中的“A”使用“0x00 0x41”两字节表示;“中”使用“0x4e 0x2d”两字节表示。文件开头的“0xfe 0xff”表示“UTF-16 BE”。

image-20240408195132906
3
UTF-8

对于 UTF-16 LE、UTF-16 BE 两种编码实现有明显的缺点

  1. 对于ascii编码的字符仍然有浪费空间的情况
  2. 对于 00 41 4e 2d 而言,只要 41 丢失,后面的所有字符编码都会因为错位而出现错误

使用 UTF8 可以解决上述所有问题。UTF8 是变长的编码方法,有 2 种 UTF8格式的文件:带有头部、不带头部。

41 e4 b8 ad 在UTF-8的文件中代表着 “A中”

image-20240408195723924 image-20240408195738094

对于 ASCII 字符,在 UTF8 文件中直接用其 ASCII 码来表示

对于非 ASCII 字符,使用变长的编码:每一个字节的高位都自带长度信息

image-20240408195911521

上图中,0xe4 的二进制是“11100100”,高位有 3 个 1,表示从当前字节起有 3 字节参与表示 UNICODE;
0xb8 的二进制是“10111000”,高位有 1 个 1,表示从当前字节起有 1 字节参与表示 UNICODE;
0xad 的二进制是“10101101”,高位有 1 个 1,表示从当前字节起有 1 字节参与表示 UNICODE;
除去高位的“1110”、“10”、“10”后,剩下的二进制数组合起来得到“01001110001101”,它就是 0x4e2d,即“中”的 UNICODE 值。
使用 UTF8 编码时,即使 TXT 文件中丢失了某些数据,也只会影响到当前字符的显示,后面的字符不受影响。

0001101”,它就是 0x4e2d,即“中”的 UNICODE 值。
使用 UTF8 编码时,即使 TXT 文件中丢失了某些数据,也只会影响到当前字符的显示,后面的字符不受影响。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值