欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

终于搞明白Unicode,ASCII,UTF8,UCS2编码是啥了

程序员文章站 2022-07-14 19:02:18
...

【本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究。若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!】

前言

本文起因于一次我使用WPS的表格另存为功能导出为TXT文本,如下图所示:

终于搞明白Unicode,ASCII,UTF8,UCS2编码是啥了

WPS 提示保存的文本文件的类型为 Unicode ,事实上这句提示很废话。

因为众所周知,Unicode 只是一套编码标准,而不是具体的编码实现,简而言之只是提供了二进制与具体字符之间的对应关系。相信在实际开发中应该没有人在程序中指定编码格式为 Unicode 吧。

我在第一次读取导出的 txt 文件时是尝试的 utf-8 编码,代码如下:

const fs = require('fs')
fs.readFile('文本.txt',{encoding: 'utf8'},(err, data) => {
    console.log(data)
})

没想到打印输出的全是乱码,没事,换个编码方式再尝试下。

fs 模块支持的编码方式包括 utf8、ucs2、ascii、binary、base64、hex。除了utf8 之外,属于 Unicode 编码标准的就是 ucs2 了,换成 ucs2 之后果然得到了正确的输出文字。

问题来了,utf8 和 ucs2 的区别是什么呢?别急,等我慢慢道来。

ASCII编码

先来了解一下编码的“祖宗” ASCII(American Standard Code for Information Interchange)即美国信息交换标准代码。它主要用于显示现代英语,包含了阿拉伯数字、大小写英文字母以及一些常用英式标点符号等。

简单来说,ASCII 编码使用 8 位共 1 字节的二进制数表示字符,范围从 0000 0000 到 0111 1111,可以表示 128 个字符。

Unicode 字符集中对这 128 个字符的编码与 ASCII 是一致的。

UTF-8编码

根据笔者在*上的学习所得,utf-8 是一种针对 Unicode 的可变长度字符编码,也是一种前缀码。它可以用一至四个字节对Unicode字符集中的所有有效编码点进行编码,属于 Unicode 标准的一部分。

UTF-8 编码的规则还可以用下表所表示:

字节数 二进制
1字节 0xxxxxxx
2字节 110xxxxx 10xxxxxx
3字节 1110xxxx 10xxxxxx 10xxxxxx
4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

因此,对 UTF-8 编码中的任意字节,根据第一位是否为 0,可判断是否为 ASCII 字符;根据前二位,可判断该字节是否为一个字符编码的第一个字节;根据前四位(如果前两位均为 1 ),可确定该字节为字符编码的第一个字节,并且可判断对应的字符由几个字节表示;根据前五位(如果前四位为 1 ),可判断编码是否有错误或数据传输过程中是否有错误。

UTF-16编码

【本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究。若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!】

看下*的专业解释:

UTF-16 是 Unicode 字符编码五层次模型的第三层:字符编码表(Character Encoding Form,也称为"storage format")的一种实现方式。即把Unicode字符集的抽象码位映射为16位长的整数(即码元)的序列,用于数据存储或传递。Unicode字符的码位,需要1个或者2个16位长的码元来表示,因此这是一个变长表示。

虽然有些晦涩难懂,但我们依旧可以得出,UTF-16 编码实现只支持通过 2 字节或者 4 字节去表示 Unicode 字符;也可以得出 UTF-16 编码实现不兼容 ASCII 编码(ASCII编码使用 1 字节来进行存储)。

UCS-2编码

我在*的学习中,看到 UCS-2 词条放在了 UTF-16 词条文章下方,并有写明 UTF-16 可看成是 UCS-2 的父集。这是为什么呢?

如果把 UTF-16 支持的 Unicode 字符范围分为两块,即如下表所示:

Unicode范围 UTF-16编码方式
U+000~U+FFFF 2 Byte存储
U+10000~U+10FFFF 4 Byte存储

UTF-16 编码实现和 UCS-2 编码实现的区别就在于 UCS-2 只支持 UTF-16 编码中对U+000~U+FFFF范围内的Unicode字符。

对于小于 0x10000 的 UCS 码,UTF-16 编码就等于UCS码。现在如果有软件声称自己支持 UCS-2 编码,那其实是在说它不能支持在 UTF-16 中超过 2 字节的字集。

后记

到此,我们终于搞明白了 UTF-8 和 UCS-2 编码方式的区别,明白了他们虽同属于 Unicode 编码标准实现体系的一部分,但实际对 Unicode 字符编码的实现完全不同。以后,如果再看到存储为 Unicode 文本,你可以尝试下以 UCS-2 格式进行解码,相信大部分情况下都是行得通的。

忽略历史原因,只用下面这一张图就足够解释 Unicode 字符集的编码问题:

终于搞明白Unicode,ASCII,UTF8,UCS2编码是啥了

最后提供一个查看 Unicode 字符与编码的网站 Unicode字符百科

版权声明

【本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究。若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!】

终于搞明白Unicode,ASCII,UTF8,UCS2编码是啥了