字符编码概念及JS中相关应用

669 阅读7分钟

Endianness(字节序)

字节序,或字节顺序("Endian"、"endianness" 或 "byte-order"),描述了计算机如何组织字节,组成对应的数字。   每个内存存储位置都有一个索引或地址。每一 字节可以存储一个 8位数字(即 介于0x00 和 0xff 之间 0~255),因此,你必须保留不止一个字节来储存一个更大的数字。

  • little-endian 现在,大部分需占用多个字节的数字排序方式是 little-endian(译者注:可称小字节序、低字节序,即低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。与之对应的 big-endian 排列方式相反,可称大字节序、高字节序),所有的英特尔处理器都使用 little-endian。little-endian 的意思是使用低位储存更重要的信息,least-to-most-significant(最低有效(least significant)字节取第一个位置,或者说,地址最低的位置),可类比欧洲通用的日期书写方式(例如,31 December 2050。译者注:年份是最重要的,月份其次,日期最后)。
  • big-endian 自然, big-endian 是相反的顺序, 可类比 ISO 日期格式(例如 2050-12-31)。big-endian 通常被称作"网络字节顺序"("network byte order"), 因为互联网标准通常要求数据使用 big-endian 存储,从标准 Unix 套接字(socket)层开始,一直到标准化网络的二进制数据结构。此外,老式 Mac 计算机的 68000 系列 和 PowerPC(译者注:IBM 与 Apple 公司联合生产的个人台式机)微处理器曾使用 big-endian。

举个例子,用不同字节序存储数字 0x12345678(即十进制中的 305 419 896):

  • little-endian:0x78 0x56 0x34 0x12
  • big-endian:0x12 0x34 0x56 0x78
  • mixed-endian(文物,非常罕见):0x34 0x12 0x78 0x56

说明:本人理解的字节高位和低位是个方向问题,高位字节从左往右;低位字节从右往左。内存是从左往右,内地地址依次增加一,故文中高地址端指的后面。

Base64

Base64是一组相似的二进制到文本(binary-to-text)的编码规则,使得二进制数据在解释成radix-64的表现形式后能够用ASCII字符串的格式表示出来。   在JavaScript中,有2个函数分别用来处理解码和编码base64 字符串:

  • atob() 解码
  • btoa() 编码
let encodedData = window.btoa("Hello, world"); // SGVsbG8sIHdvcmxk
let decodedData = window.atob(encodedData); // "Hello, world")

原码/反码/补码/整形/浮点数

  • 原码 直接将二进制按照正负数的形式翻译成二进制就可以。
  • 反码 将原码的符号位不变,其他位依次按位取反就可以得到了。
  • 补码 反码+1就得到补码。
  • 整型 以2进制本数的补码存在的;
  • 浮点数 32位(单精度float):对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。 64位(双精度float):对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。

JS API

  • ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。 ArrayBuffer 不能直接操作,而是要通过类型数组对象或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。
  • SharedArrayBuffer 对象用来表示一个通用的,固定长度的原始二进制数据缓冲区,类似于 ArrayBuffer 对象,它们都可以用来在共享内存(shared memory)上创建视图。与 ArrayBuffer 不同的是,SharedArrayBuffer 不能被分离。
  • Uint8Array 数组类型表示一个8位无符号整型数组,创建时内容被初始化为0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。
  • Uint8ClampedArray (8位无符号整型固定数组) 类型化数组表示一个由值固定在0-255区间的8位无符号整型组成的数组; 如果你指定一个在 [0,255] 区间外的值,它将被替换为0或255;如果你指定一个非整数,那么它将被设置为最接近它的整数。(数组)内容被初始化为0。一旦(数组)被创建,你可以使用对象的方法引用数组里的元素,或使用标准的数组索引语法(即使用方括号标记)。
  • Uint16Array 数组类型表示一个16位无符号整型数组,创建时内容被初始化为0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。
  • Uint32Array 数组类型表示一个32位无符号整型数组,创建时内容被初始化为0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。
  • Int8Array 类型数组表示二进制补码8位有符号整数的数组。内容初始化为0。 一旦建立,你可以使用对象的方法引用数组中的元素,或使用标准数组索引语法( 即,使用括号注释)。
  • Int16Array 类型数组表示二进制补码16位有符号整数的数组。内容初始化为0。 一旦建立,你可以使用对象的方法引用数组中的元素,或使用标准数组索引语法( 即,使用括号注释)。
  • Int32Array 类型数组表示二进制补码32位有符号整数的数组。内容初始化为0。 一旦建立,你可以使用对象的方法引用数组中的元素,或使用标准数组索引语法( 即,使用括号注释)。
  • Float32Array 类型数组代表的是平台字节顺序为32位的浮点数型数组(对应于 C 浮点数据类型) 。 如果需要控制字节顺序, 使用 DataView 替代。其内容初始化为0。一旦建立起来,你可以使用这个对象的方法对其元素进行操作,或者使用标准数组索引语法 (使用方括号)。
  • Float64Array 类型数组代表的是平台字节顺序为64位的浮点数型数组(对应于 C 浮点数据类型) 。 如果需要控制字节顺序, 使用 DataView 替代。其内容初始化为0。一旦建立起来,你可以使用这个对象的方法对其元素进行操作,或者使用标准数组索引语法 (使用方括号)。
  • DataView 视图是一个可以从 ArrayBuffer 对象中读写多种数值类型的底层接口,使用它时,不用考虑不同平台的字节序问题。
Type Value Range Size in bytes Description Web IDL type Equivalent C type
Int8Array -128 to 127 1 8-bit two's complement signed integer byte int8_t
Uint8Array 0 to 255 1 8-bit unsigned integer octet uint8_t
Uint8ClampedArray 0 to 255 1 8-bit unsigned integer (clamped) octet uint8_t
Int16Array -32768 to 32767 2 16-bit two's complement signed integer short int16_t
Uint16Array 0 to 65535 2 16-bit unsigned integer unsigned short uint16_t
Int32Array -2147483648 to 2147483647 4 32-bit two's complement signed integer long int32_t
Uint32Array 0 to 4294967295 4 32-bit unsigned integer unsigned long uint32_t
Float32Array 1.2x10-38 to 3.4x1038 4 32-bit IEEE floating point number ( 7 significant digits e.g. 1.1234567) unrestricted float float
Float64Array 5.0x10-324 to 1.8x10308 8 64-bit IEEE floating point number (16 significant digits e.g. 1.123...15) unrestricted double double
BigInt64Array -263 to 263-1 8 64-bit two's complement signed integer bigint int64_t (signed long long)
BigUint64Array 0 to 264-1 8 64-bit unsigned integer bigint uint64_t (unsigned long long)