Unicode字符串中每个字符的二进制数据如何与下一个字符的二进制数据分开?

Tee*_*moh 1 javascript string binary encoding character-encoding

在JavaScript中,我可以使用charCodeAt-method从单个字符获取Unicode。

当我使用它将字符串转换为unicode号时,我将得到以下结果:

"A".charCodeAt(0) === 65

"?".charCodeAt(0) === 2410

将这些十进制数字转换为二进制数字将如下所示:

"A".charCodeAt(0).toString(2) === "1000001" // 1 byte, with padleft: "01000001"

"?".charCodeAt(0).toString(2) === "100101101010" // 2 bytes, with padleft: "0000100101101010"

这意味着,?符号使用2个字节来表示。但是阅读过程如何知道呢?

也可能是两个不同的字符" ""j"

String.fromCharCode(parseInt("00001001", 2)) === " " // horizontal tabulator

String.fromCharCode(parseInt("01101010", 2)) === "j"

那么二进制读取过程如何知道一个字符使用多少个字节?是否有分隔符之类的东西?

dan*_*n04 5

Unicode将每个字符*映射到整数“代码点”。有效的代码点是U + 0000到U + 10FFFF,允许超过一百万个字符(尽管大多数字符尚未分配)。

(*比这要复杂一些,因为存在“组合字符”,其中一个用户可感知的字符可以用多个代码点表示。有些字符既有预先组成的,也有分解后的表示。例如,西班牙语字母ñ可以表示为单个代码点U + 00F1,也可以表示为序列U + 006E U + 0303(n+组合代字号)。

可以使用三种不同的编码形式(不算另类编码,如UTF-9和UTF-18)来表示字符串中的Unicode字符。

UTF-32是最简单的一种:每个代码点都由一个32位整数表示。因此,例如:

  • A (U + 0041)= 0x00000041
  • ñ (U + 00F1)= 0x000000F1
  • ? (U + 096A)= 0x0000096A
  • (U + 1F4AA)= 0x0001F4AA

尽管简单,但UTF-32使用大量内存(每个字符4个字节),很少使用。

UTF-16使用16位代码单元。字符U + 0000至U + FFFF(“基本多语言平面”)直接表示为单个代码单元,而字符U + 10000至U + 10FFFF则表示为“代理对”。具体来说,您从代码点减去0x10000(得出20位数字),并使用这些位填写二进制序列110110xxxxxxxxxx 110111xxxxxxxxxx。例如,

  • A (U + 0041)= 0x0041
  • ñ (U + 00F1)= 0x00F1
  • ? (U + 096A)= 0x096A
  • (U + 1F4AA)= 0xD83D 0xDCAA

为了使该系统正常工作,代码点U + D800至U + DFFF被永久保留用于此UTF-16代理机制,并且永远不会分配给“实”字符。

这是一种向后兼容的“ hack”,可以在1990年代的平台上表示完整的17-“平面” Unicode代码空间,该平台的设计期望Unicode字符始终为16位。这包括Windows NT,Java和JavaScript。

UTF-8表示具有1-4个字节序列的Unicode代码点。具体来说,每个字符用以下最短的字符表示:

  • 0xxxxxxx
  • 110xxxxx 10xxxxxx
  • 1110xxxx 10xxxxxx 10xxxxxx
  • 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

因此,使用前面的示例:

  • A (U + 0041)= 0x41
  • ñ (U + 00F1)= 0xC3 0xB1
  • ? (U + 096A)= 0xE0 0xA5 0xAA
  • (U + 1F4AA)= 0xF0 0x9F 0x92 0xAA

这种编码具有以下特性:可以从第一个字节的值确定序列中的字节数。此外,可以容易地将前导字节与连续字节区分开:

  • 0xxxxxxx =单字节字符(与ASCII兼容)
  • 10xxxxxx = 2、3或4字节字符的连续字节
  • 110xxxxx = 2字节字符的前导字节
  • 1110xxxx = 3字节字符的前导字节
  • 11110xxx = 4字节字符的前导字节
  • 11111xxx =未使用