前端编码“三剑客”(零)前置基础

403 阅读6分钟

《前端编码系列》

前端编码“三剑客”(零)前置基础

前端编码"三剑客"(一)Base64

前端编码”三剑客“(二)URI

一、前缀符号

0b 0o 0x

二进制 Binary八进制 Octal十进制 Decimal十六进制 Hexadecimal
特定前缀0b0B0或·0o0x0X
示例10b10100o12100xA
示例20b110100o32260x1A

\x

在字符串中,\x前缀用来表示一个十六进制的转义序列。它后面跟着两个十六进制数字。示例:\x41 表示字符 'A'(因为A的ASCII码的十六进制是41)

\u

在字符串中,\u前缀用来表示一个Unicode字符。它后面跟着四个十六进制数字,表示该字符的Unicode码点。示例:\u0041 表示字符 'A'(因为'A'的Unicode码点是U+0041)



二、ASCII

全称"American Standard Code for Information Interchange,美国信息交换标准代码",是基于拉丁字母的一套电脑编码系统。至今为止共定义了128个字符,包括95个可显示的字符(编号范围是32-126)和33个无法显示的字符(多数为控制字符)。

ASCII 用一个字节(8个二进制位) 来储存字符,理论上一共可以表示256个字符,但最前面一位的0没有使用(统一为0),于是一共包含128个字符。

image-20241006003134782



三、Unicode-统一码

3.1 码点,编码值

Unicode是一个容纳了世界上大多数文字系统的字符集,其中每个字符都有唯一的编码值(code point,常被译为 “码点” ),编码值范围是:0 - 10FFFF,一共1114112个值(超过1百万)。目标是消除不同国家地区之间由于字符集不同导致的乱码问题。

Unicode 为每个字符分配了一个唯一的码点,这个码点是一个数值,用于唯一标识字符。这些码点通常用十六进制数表示,并且前面加上 "U+" 前缀来明确指出这是一个 Unicode 码点。

UNICODE.org

image-20241006120116112

Unicode仅规定了符号的二进制代码(编码值) ,但没有规定这个二进制代码如何储存 (编码方式)

Unicode和ASCII的关系:Unicode是在ASCII基础上发展的,对ASCII是兼容的,对于ASCII中的128个字符,它们在ASCII和Unicode中的编码值(code point)是一致的。


3.2 BOM,字节顺序

Byte Order Mark,字节顺序标记,是一个用于标识文件中字节顺序的特殊字符。在 UTF-16 和 UTF-32 这两种编码方式中可能使用 BOM

LE

Little-Endian小端序。最低有效字节储存在最低内存地址处。常作为网络协议中的字节序。举个例子:对于16位值 0xABCD

image-20241007203502062

BE

Big-Endian大端序。最高有效字节储存在最低内存地址处。常作为现代计算机系统的字节序。还是以16位值0xABCD为例

image-20241007203621172


3.3 UTF,编码方式

UTF(Unicode Transformation Format,Unicode 转换格式) ,主要有3种

特点优点缺点
UTF-32使用4个字节的定长编码编解码规则最简单、效率高Unicode编码值最大需要占用3个字节空间,
也就是说任何一个code point都会浪费1~3个字节的空间
UTF-16使用2或4个字节的变长编码--
UTF-8使用1~4个字节的变长编码最省空间-



Q:同一个字符/码点,用UTF-32/16/8编码之后,表现出来的数值一样吗?A:不一样。

"中"UTF-8UTF-16BEUTF-32BE
二进制11100100 10111000 1010110101001110 0010110100000000 00000000 01001110 00101101
十进制149894852001320013
十六进制\xE4\xB8\xAD\u4E2D0000 4e2d

image-20250102000110326

"a"UTF-8UTF-16BEUTF-32BE
二进制0110000100000000 0110000100000000 00000000 00000000 01100001
十进制979797
十六进制6100610000 0061



UTF-32

UTF-32的编码规则

  • 固定为4个字节的长度
  • 直接映射,Unicode码点直接映射到对应的32位值,示例:U+0041(字母“A”) => 0x00000041
  • 字节序:可以使用BOM来表示字节序(也可以不使用),LE 对应的 BOM 是 0x0000FEFF,BE 对应的 BOM 是 0xFFFE0000



UTF-16

UTF-16的编码规则

  • 规则1:基本平面的 code point(范围在U+0000 ~ U+FFFF)使用2个字节表示,辅助平面的 code point(范围在U+100000 ~ U+10FFFF)使用4个字节表示
  • 规则2:16个辅助平面(范围在U+10000 ~ U+10FFFF)一共有 fffff16 也即 220 个字符,将这20位拆成2半,将高10位映射在 U+D800 ~ U+DBFF,称为“高位代理”;将低10位映射在 U+DC00 ~ U+DFFF,称为“低位代理”。其中 U+D800 ~ U+DBFF 的区间是基本平面中未使用、特定留给辅助平面区间使用的。目的是为了达到“前缀无歧义”的效果。



UTF-8

UTF-8的编码规则

  • 规则1:不同范围的 code point 使用不同长度的编码
  • 规则2:编码字节长度为1时前缀为 0,编码字节长度为2时前缀为 110,编码字节长度为3时前缀为 1110,编码字节长度为4时前缀为 11110
  • 规则3:除了首字节,其余字节前缀为 10

img



3.4 拓展1:如何查看码点

const str = "hi你好";
str.codePointAt(0); //104
str.charCodeAt(0);  //104str.codePointAt(2);  //20320
str.charCodeAt(2);   //20320



3.5 拓展2:如何查看原始字节流

在 Mac 上可以通过以下命令

xxd filename  #查看文本文件的原始字节流,以16进制的形式
xxd -b filename #查看文本文件的原始字节流,以2进制的形式
​
file -I filename  #查看文本文件的编码格式。输出示例:index.txt: text/plain; charset=utf-8 
​
iconv -f UTF-8 -t UTF-16BE index.txt > index_utf16be.txt  #转换文本文件的编码格式,输出为新文件



四、Uint8Array

Uint8Array MDN

Uint8Array 数组类型表示一个 8 位无符号整型数组,创建时内容被初始化为 0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。

TextEncoder MDN

TextEncoder 接受码位流作为输入,并提供 UTF-8 字节流作为输出。

const TE = new TextEncoder();
​
TE.encode('h')  // Uint8Array(1) [ 104 ]



参考文献

ASCII表大全

ASCII 表 | 菜鸟教程

字符编码笔记:ASCII,Unicode 和 UTF-8 | 阮一峰

计算机基础:今天一次把 Unicode 和 UTF-8 说清楚 | 知乎

Unicode官网

汉字Unicode编码表