字节和字节序(前端视角)

364 阅读3分钟

image.png

前端字节操作方法

ArrayBuffer

  1. 前端有一个类叫ArrayBuffer,它是一个数组,可以用来存储一定数量的“字节”。
  2. 一个字节等于8位,一位(1bit)可以存一个二进制数据,要么存0,要么存1。
  3. 那么一个字节就可以存8个二进制数字,也就是说一个字节所能存的数字一定在 00000000~11111111 范围内,超出这个范围就得用更多字节来存。数字还分有符号和无符号,这里不展开了。 image.png 一个字节可以存储的数据量

Typed Array 和 Data View

  1. ArrayBuffer不可以直接读写,得借住Typed ArrayData View
  2. 比如借助Typed Array
// 创建一个长度为10的buffer
const buffer = new ArrayBuffer(10)

// 创建一个无符号8位Typed Array
const view = new Uint8Array(buffer)
view[0] = 255
view[1] = 100
  1. 又比如借助Data View
 const data = new ArrayBuffer(10)
 const view = new DataView(data)
 view.setInt8(0, 255)

字节序

如上所说,当调用DataView.setInt8(0, 255)时,内存中的数据如下:

image.png 查看MDN文档可以看到DataView.setInt8是没有第三个参数的,而DataView.setInt16 / DataView.setInt32等需要传第三参数littleEndian,这就是字节序。因为setInt8正好是设置一个字节,没有顺序的概念;从setInt16开始,就要一次向多个字节中写数据,就有写入顺序的概念。

先看一下大端字节序的表现

 const data = new ArrayBuffer(10)
 const view = new DataView(data)
 view.setInt32(0, 258, false) // 第三个参数传false,也是默认值

写入32位整形需要一次操作4个字节(4*8=32)

image.png

再看一下小端字节序的表现

     const data = new ArrayBuffer(10)
     const view = new DataView(data)
     view.setInt32(0, 258, true) // 第三个参数传true,表示小端字节序

image.png

读数据时的字节序

读字节与写字节一样,如果你读一个字节,那没有字节序可言,但你读多个字节时必须要指定字节序。比如


     const data = new ArrayBuffer(10)
     const view = new DataView(data)
     view.setInt32(0, 258, true)
     view.getInt8(0) // 只读一个字节
     view.getInt32(0, true) // 读一个32位整形(4字节),第二个参数指定使用什么字节序

一般以什么字节序写入,就用什么字节序读出,否则会读到与写入时不一样的结果。

比如下面这张图,我是用大端字节序写入了一个258数字。

image.png

正确的计算方式是

image.png

如果以小端字节序写入,内存里就是下面这样。

image.png 如果却用大端字节序来读就变成了

image.png 那你会发现,写入258,读出却是33619968

用字节表达现实世界的信息

其实字节是纯粹的,每个字节里就存了8位,每位有两种可能,0或1。至于一次读几个字节;以什么样的顺序去读;读出来的这些字节表示什么意义,那是需要人去设计的。

比如

  1. 一个字节可以存0-255,RGB颜色值正好是0-255,那3个字节就可以表示一组rgb,也就是一个像素信息,一个这样的字节数组就可以表示一张图片。

  2. 在ASCII码中一个字节可以表示一个字符,字母A的ASCII码是65,二进制表示就是 01000001。也就是说,当你读到一字节里面的数据是 01000001 ,又和对方约定了,这里表示的是一个通过ASCII编码的信息,那你就知道了,对方在这个字节里放了一个字母A。 image.png

  3. gbk编码用固定两个字节表示一个符号,如果你读到两个字节 1100110111110101 (16进制表示是 CDF5),通过gbk对照表就知道这表示 “王” 这个汉字。 image.png image.png

10分钟带你了解什么是ArrayBuffer

理解字节序(阮一峰)