目录
TypedArrays
Buffer
WebWorker
注意事项
二进制数据和文本数据是我们常见的两种格式数据。而在某些应用场景,则需要我们使用JavaScript去操作读写二进制格式文件,比如WebSocks获取原始数据、操作音视频文件、获取商业软件格式的数据等。尽管JavaScript是一门动态语言(弱类型),不擅长于处理二进制数据,但是我们可以使用JavaScript的类型化数组 TypedArrays操作二进制数据。
JavaScript的类型化数组(TypedArrays)提供了一个更加高效的机制来访问和处理二进制数据。以下是MDN官网对TypedArrays的介绍:
一个TypedArray 对象描述一个底层的二进制数据缓存区的一个类似数组(array-like)视图。事实上,没有名为 TypedArray的全局对象,也没有一个名为的 TypedArray构造函数。相反,有许多不同的全局对象,下面会列出这些针对特定元素类型的类型化数组的构造函数:
// create a TypedArray with a size in bytes
const typedArray1 = new Int8Array(8);
typedArray1[0] = 32;
const typedArray2 = new Int8Array(typedArray1);
typedArray2[1] = 42;
console.log(typedArray1);
// expected output: Int8Array [32, 0, 0, 0, 0, 0, 0, 0]
console.log(typedArray2);
// expected output: Int8Array [32, 42, 0, 0, 0, 0, 0, 0]
为了达到最大的灵活性和高效性,JavaScript的TypedArray分为两个部分:缓冲区和视图。
缓冲区由ArrayBuffer实现,一个缓冲区是一个代表某个数据块的对象。它没有格式,而且没有提供一个机制来访问或操纵其中的内容。为了存取缓冲区中 的内容,你需要创建一个视图。视图提供了一个环境(context),包括数据类型、起始偏移量以及元素数量。它把数据转化为实际上的类型化数组。视图由 ArrayBufferView和它的一些子类实现。
从上述的描述可以看出,TypedArrays弥补了弱类型的JavaScript的缺陷。在学习TypedArrays之前,必须先要了解计算机的存储数据各种基本类型,int, uint(无符号整形),float....。TypedArrays向我们提供多种类型的视图实例:
Int8Array是指,数组中的每一项都是一个占8位(1字节)的整型数据。在处理二进制数据,还要考虑二进制的存储是按照小端法还是大端法。后面在介绍Buffer类会提及。
附上TypedArrays 的官网链接:MDN document
MDN官网上没有找到Buffer类的介绍,但在Node.js的官网上有详细的介绍Buffer的使用和实例,附上链接:Buffer文档
我在处理二进制数据时,经常把ArrayBuffer直接实例化为Buffer类去操作二进制数据流,因为Buffer提供了很多很方便的方法让我们去解析字节数据。包括根据字符编码从字节码解析出中文或者从中文解析除特定编码的二进制,开辟内存空间,读取不同端序的字节数据等等。
// Creates a zero-filled Buffer of length 10.
const buf1 = Buffer.alloc(10);
// Creates a Buffer of length 10, filled with 0x1.
const buf2 = Buffer.alloc(10, 1);
// Creates an uninitialized buffer of length 10.
// This is faster than calling Buffer.alloc() but the returned
// Buffer instance might contain old data that needs to be
// overwritten using either fill() or write().
const buf3 = Buffer.allocUnsafe(10);
// Creates a Buffer containing [0x1, 0x2, 0x3].
const buf4 = Buffer.from([1, 2, 3]);
// Creates a Buffer containing UTF-8 bytes [0x74, 0xc3, 0xa9, 0x73, 0x74].
const buf5 = Buffer.from('tést');
// Creates a Buffer containing Latin-1 bytes [0x74, 0xe9, 0x73, 0x74].
const buf6 = Buffer.from('tést', 'latin1');
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
另外,Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document
、window
、parent
这些对象
从上述简单的介绍,可以看出,WebWorker适合处理与DOM 对象无关的计算程序。因此,在处理二进制数据时可以使用Web Worker去创建一个新的Worker 线程去运行处理程序,从而提高运算时间,避免与UI交互产生冲突。
在实际的读取二进制的过程中,我们通常都需要读取特定编码的中文字符。此时,我们需要根据设计好的中文编码规则去解析二进制。例如GBK的中文编码规则是每个汉字使用双字节表示,而UTF-8是使用可变长字节去存储字符,英文使用一个字节,中文使用三个字节。
因此,在读取中文时,必须清楚知道二进制流中中文字符的编码,才能解析得到正确的内容。