一篇文章让你测底弄懂 ASCII,Unicode 和 UTF-8

在我学习 JavaScript 的时候, 获取字符串的长度的时候,大多数能够获取到正确的字符串长度,但是有些字符获取的长度却大不相同,到底是为什么会导致这样的发生。

在早初的计算机,所有的信息都是靠二进制存储在计算机中的,美国制定了一套字符编码,使得英语字符与二进制之间产生一个映射。每一个二进制位都是由 0 和 1 两种组成的,八位(也就是八个0或者1组成的)被称为是一个字节,八位最多可以组合成 256 中状态。(不懂转换的可以使用转换工具 进制转换)。

 这种编码方式称为 ASCII 码。 ASCII 一共规定了 128 个字符的编码,其中还包括 空格是32(二进制 00100000),大写字母 A 是 65(二进制是 01000001)。128个字符包含了英文字母以及32个不能打印出来的控制符号。

数字 32–126 打印字符。

0–31 分配给了控制字符,不可以打印。

十进制字符十进制字符
016数据链路转意
1头标开始17设备控制 1
2正文开始18设备控制 2
3正文结束19设备控制 3
4传输结束20设备控制 4
5查询21反确认
6确认22同步空闲
7震铃23传输块结束
8backspace24取消
9水平制表符25媒体结束
10换行/新行26替换
11竖直制表符27转意
12换页/新页28文件分隔符
13回车29组分隔符
14移出30记录分隔符
15移入31单元分隔符

除了上述的 128 个字符之外,ASCII 还剩下许多遗留的符号位。

而且对于英语来说,128 个符号编码就够了,但是对于其他语言来说,每个国家都有自己的语言,然后其他国家就利用这剩下的码位,编写自己国家的符号编码,比如在法语中,é(这种字符上带注意就是法语)的编码位 130 (二进制10000010),但是 编码位 130 在希伯来中却代表了字母 ג,所以每个国家都来都来利用 128~255 这一段来编码,对于0~127符号是固定的。

因为不同国家重复的使用一块地方,在转码的时候容易造成乱码。并且 对于我们国家使用汉语的来说,哪怕文字都多达10万左右。用一个字节8位来存储是完全不够的,那么怎么办呢?很简单,一个字符由 256 种存法,那一个字节不够存,我用两个,三字,甚至四个字节来存,不就可以了嘛。

Unicode的诞生。

Unicode 就是用来解决这种的。总有人会意识到应该提出一种编码方式,用来收集所有国家的字符。它用数字记录了所有国家的符号对应的数字。我们不需要关心如何规定的,只需要知道每个字符都对应一个不会重复的二进制数。

我们已经知道了 Unicode 为了解决编码存储范围小,所以采用更大的字节来存储字符。那么Unicode 又怎么会知道自己存储的是需要几个字节的字符呢。先不说Unicode 有多大,我们就假设Unicode 是一个字典,最后一页的最后一位是代码占用四个字节。最简单的莫过于直接规定所有的字符存储都为 4 个字节, 那么所有的字符统统在范围内,只需要前面补 0 即可。这样固然简单,但这也太浪费空间了吧,我要是使用 ASCII 前几位,明明是占一个字节,硬生生补 0 成为 4 个字节,这样合理吗?

因为上文原因,诞生了一种种的 Unicode 的实现方式。

UTF-8 (是 Unicode 的实现方式之一)。

互联网的普及,强烈要求出现统一的编码方式。UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式。 还有UTF-16,UTF-32, 毫无疑问,都是 Unicode 的实现方式。 UTF-32 就是像上面的实现一样,使用定长的4个字节,看起来比较方便,但是却不如 UTF-8 和 UTF-16 .

而 UTF-8 的最大的一个特点就是使用一种 与 UFT-16定长不同的, 变长的编码方式。它是使用 1~4个字节来表示的,可以根据字符来变化不同字节长度。

UTF-8 的 编码规则:

1. 对于单字节来说,也就是 符合 ASCII 编码方式的八位,字节的第一位被设置为 0,后面的 7 位对应这个字符的 Unicode 码点。 英文中的 0~127(二进制  01111111, 十六进制 0000 007F)。

2. 对于需要 N 个字节来表示的字符 (N > 1) 来说,第N个字节(右面第一个位第一个字节算起)的前 N 位都是 1,第 n + 1 位 设置为 0, 然后 后面(从左往右数)的字节前两位一律设为10。剩下的二进制位用这个字符的 Unicode 码点来填充。

Unicode 十六进制码点范围UTF-8 二进制
0000 0000 - 0000 007F0xxxxxxx
0000 0080 - 0000 07FF110xxxxx 10xxxxxx
0000 0800 - 0000 FFFF1110xxxx 10xxxxxx 10xxxxxx
0001 0000 - 0010 FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

以 严 的 Unicode 是 4E25 (100111000100101), 可以发现它是属于 第三行的 1110xxxx 10xxxxxx 10xxxxxx 表示。因此 严 需要三个字节来表示,我们用 100111000100101 来填充 1110xxxx 10xxxxxx 10xxxxxx,从右向左来填充, 第一个字节的xxxxxx,我们用 100101来填充,第二个字节的xxxxxx我们用111000填充,第三个字节的xxxx我们用 100来填充,多处的位补 0.

所以我们得到了 Unicode 4E25的 UFT-8编码 11100100 10111000 10100101, 转为十六进制就是 E4B8A5。

我们也可以通过网上一些工具来实现 UTF-8 到 Unicode 的实现。注意:我说的是实现,并不是转换,因为 UTF-8 只能算是Unicode的一种实现形式,二者并不是对立的。

像java 和 c 等语言是使用的 UTF-8 语言。 JavaScript 使用了UTF-16格式来对于字符串编码。下一篇我们会着重讲解一下JavaScript中的UTF-16。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值