文 / 泽白
最近接触了一些二进制读写相关的内容,重新探究了部分二进制的操作。
序言
从某种意义上讲,计算机上所有类型的信息最终都将被编码为固定大小的整数。作为实际发送和接收的数据形态,整数会被填充进不同长度的数据类型,并在读取时被赋值和转换,因此对整数的填充长度和符号的理解是非常重要的。
回顾
计算机中的信息包括数据信息和控制信息,数据信息又可分为数值和非数值信息。非数值信息和控制信息涵盖了字母、各种控制符号、图形符号等,它们都以二进制编码方式存人计算机并得以处理,这种对字母和符号进行编码的二进制代码称为字符编码(character code
)。主要相关概念有:
- 字节:是计算机中存储数据的基本单元,一个 8 位的二进制数。比如以十六进制表示的
0x00
,0x01
,0xFF
- 字符:抽象意义上的一个符号,是各种文字、标点符号、图形符号、数字等的总称
- 字符集:是一组抽象的字符集合。各个国家和地区制定了各自语言所需的字符集。比如英文字符集
ASCII
、简体中文字符集GB2312
、繁体中文字符集BIG5
、日文字符集JIS
等 - 字符编码:规定了每个字符分别用一个字节还是多个字节表示,及用哪个字节值来存储
实战
Arraybuffer / TypedArray / DataView
Arraybuffer
是 js
中的内置对象,平常很少会用到,是用来表示和操作结构化的缓冲区数据。它是字节数组,js
中是没有表示单个字节单位的对象的,Arraybuffer
即是最小单位的内置对象。详细可看MDN 定义
const buffer = new ArrayBuffer(8);
console.log(buffer.byteLength); // 8
Arraybuffer
中的内容是不能直接操作的,需要通过 TypedArray
和 DataView
对象来操作。
TypedArray
对象描述了描述了一个底层的二进制数据缓冲区(binary data buffer
)的一个类数组视图(view
)。js
中是没有名为 TypedArray
的对象的,可以通过以下对象构造 TypedArray
对象
new Int8Array();
new Uint8Array();
new Uint8ClampedArray();
new Int16Array();
new Uint16Array();
new Int32Array();
new Uint32Array();
new Float32Array();
new Float64Array();
有了 TypedArray
就可以像操作数组一样操作 Arraybuffer
const buffer = new ArrayBuffer(8);
const int8Array = new Int8Array(buffer, 1, 4);
console.log(int8Array.length); // 4
Int8Array
原型对象上的方法基本和数组类似,例如:
Int8Array.prototype.entries();
Int8Array.prototype.every();
Int8Array.prototype.fill();
Int8Array.prototype.filter();
Int8Array.prototype.find();
Int8Array.prototype.findIndex();
Int8Array.prototype.forEach();
// ...
DataView
内置对象提供了和 TypedArray
对象类似的功能,可以直接通过 new DataView()
创建一个 DataView
视图,用来从二进制 Arraybuffer
对象中读写多种数值类型。
const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);
view.setUint16(0, 255);
console.log(view.getUint16(0)); // 255
console.log(view.getUint8(0)); // 0
console.log(view.getUint8(1)); // 255
base64
Base64 是网络上最常见的用于传输 8 比特字节代码的编码方式之一,也是前端不会陌生的一大利器。
atob / btoa
atob
和 btoa
两个方法是原生的将字符和 Base64
编码转换的方法,兼容性也比较好,可以参考CanIUse: atob
const Str = 'Foo';
const BStr = btoa(Str);
console.log(BStr); // 'Rm9v'
console.log(atob(BStr)); // 'Foo'
转译步骤(粗略)
- 将
Foo
三个字符的ASCII
编码转换为二进制放入一个 24 位的缓冲区 - 每次取 6 位作为
Base64
索引值 - 通过索引值查表,即可得到
Base64
编码
小结
二进制确实距离平常的前端开发比较遥远,文件上传会涉猎一些,但更多的是通过表单直接将文件以相应的格式通过 http
请求发送出去,很少会操作文件数据的诉求,经过一些简单的回顾,这些基础知识还是比较有趣的。学海无涯~