前言:上一篇讲的请求网络图片得到ArrayBuffer对象或Bold对象通过处理转换得到 Bold URL 后放到img元素显示,本文将介绍什么是Bold、ArrayBuffer
Blob(Binary Large Object)表示二进制类型的大对象。Blob(Binary Large Object)表示二进制类型的大对象。在数据库管理系统中,将二进制数据存储为一个单一个体的集合。Blob 通常是影像、声音或多媒体文件。在 JavaScript 中 Blob 类型的对象表示不可变、原始数据的类似文件对象的原始数据。
为了更直观的感受 Blob 对象,我们先来使用 Blob 构造函数,创建一个 myBlob 对象,具体如下图所示:
如图所见,Blob 对象含有两个属性:size
和 type
:
Blob 表示的不一定是 JavaScript 原生格式的数据。比如 File 接口基于 Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
Blob 由一个可选的字符串 type(通常是 MIME 类型)和 blobParts 组成:
Blob 构造函数的语法为
var aBlob = new Blob(blobParts, options);
blobParts
是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。DOMStrings会被编码为UTF-8。options
是一个可选的BlobPropertyBag字典,它可能会指定如下两个属性:
下面例子用类型化数组和字符串创建 Blob
let hello = new Uint8Array([72, 101, 108, 108, 111]); // 二进制格式的 "hello"
let blob = new Blob([hello, ' ', 'world'], {type: 'text/plain'});
注: Blob 对象是不可改变的。 我们不能直接在一个 Blob 中更改数据,但是我们可以对一个 Blob 进行分割,从其中创建新的 Blob 对象,将它们混合到一个新的 Blob 中。
ArrayBuffer 对象用来表示 「通用的、固定长度的」 原始二进制数据缓冲区。「ArrayBuffer 不能直接操作,而是要通过类型数组对象 或 DataView 对象来操作」 ,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。
new ArrayBuffer(length)
下面的例子创建了一个 8 字节的缓冲区,并使用一个 Int32Array 来引用它:
let buffer = new ArrayBuffer(8);
let view = new Int32Array(buffer);
console.log(view.length) // 2
Uint8Array 数组类型表示一个 8 位无符号整型数组(相当于字节数组),创建时内容被初始化为 0。创建完后,可以以「对象的方式或使用数组下标索引的方式」引用数组中的元素。
TypedArray是用来描述底层二进制数据缓冲区的类似数组的视图。Uint8Array 为TypedArray的子类。
new Uint8Array(); // ES2017 最新语法
new Uint8Array(length); // 创建初始化为0的,包含length个元素的无符号整型数组
new Uint8Array(typedArray);
new Uint8Array(object);
new Uint8Array(buffer [, byteOffset [, length]]);
// new Uint8Array(length);
var uint8 = new Uint8Array(2);
uint8[0] = 42;
console.log(uint8[0]); // 42
console.log(uint8.length); // 2
console.log(uint8.BYTES_PER_ELEMENT); // 1
// new TypedArray(object);
var arr = new Uint8Array([21,31]);
console.log(arr[1]); // 31
// new Uint8Array(typedArray);
var x = new Uint8Array([21, 31]);
var y = new Uint8Array(x);
console.log(y[0]); // 21
// new Uint8Array(buffer [, byteOffset [, length]]);
var buffer = new ArrayBuffer(8);
var z = new Uint8Array(buffer, 1, 4);
ArrayBuffer 本身只是一行 0 和 1 串。 ArrayBuffer 不知道该数组中第一个元素和第二个元素之间的分隔位置。
为了提供上下文,实际上要将其分解为多个盒子,我们需要将其包装在所谓的视图中。可以使用类型数组添加这些数据视图,并且你可以使用许多不同类型的类型数组。
可以在同一基本缓冲区上拥有多个视图。对于相同的操作,不同的视图会给出不同的结果。 例如,如果我们从这个 ArrayBuffer 的 Int8 视图中获取 0 & 1 元素的值(-19 & 100),它将给我们与 Uint16 视图中元素 0 (25837)不同的值,即使它们包含完全相同的位。
这样,ArrayBuffer 基本上就像原始内存一样。它模拟了使用 C 之类的语言进行的直接内存访问。「你可能想知道为什么我们不让程序直接访问内存,而是添加了这种抽象层,因为直接访问内存将导致一些安全漏洞」。
「ArrayBuffer」 对象用于表示通用的,固定长度的原始二进制数据缓冲区。你不能直接操纵 ArrayBuffer 的内容,而是需要创建一个 TypedArray 对象或 DataView 对象,该对象以特定格式表示缓冲区,并使用该对象读取和写入缓冲区的内容。
「Blob」 类型的对象表示不可变的类似文件对象的原始数据。Blob 表示的不一定是 JavaScript 原生格式的数据。File 接口基于 Blob,继承了Blob 功能并将其扩展为支持用户系统上的文件。
Blob 与 ArrayBuffer 对象之间是可以相互转化的:
下面为互相转换的例子:
var blob = new Blob(["\x01\x02\x03\x04"]),
fileReader = new FileReader(),
array;
fileReader.onload = function() {
array = this.result;
console.log("Array contains", array.byteLength, "bytes.");
};
fileReader.readAsArrayBuffer(blob);
var array = new Uint8Array([0x01, 0x02, 0x03, 0x04]);
var blob = new Blob([array]);
DataView 视图是一个可以从二进制 ArrayBuffer 对象中读写多种数值类型的底层接口,使用它时,不用考虑不同平台的字节序问题。
字节顺序,又称端序或尾序(英语:Endianness),在计算机科学领域中,指存储器中或在数字通信链路中,组成多字节的字的字节的排列顺序。
字节的排列方式有两个通用规则。例如,一个多位的整数,按照存储地址从低到高排序的字节中,如果该整数的最低有效字节(类似于最低有效位)在最高有效字节的前面,则称小端序;反之则称大端序。在网络应用中,字节序是一个必须被考虑的因素,因为不同机器类型可能采用不同标准的字节序,所以均按照网络标准转化。
例如假设上述变量 x 类型为int,位于地址 0x100 处,它的值为 0x01234567,地址范围为 0x100~0x103字节,其内部排列顺序依赖于机器的类型。大端法从首位开始将是:0x100: 01, 0x101: 23,…。而小端法将是:0x100: 67, 0x101: 45,…。
new DataView(buffer [, byteOffset [, byteLength]])
相关的参数说明如下:
「DataView 返回值」
使用 new 调用 DataView 构造函数后,会返回一个表示指定数据缓存区的新 DataView 对象。你可以把返回的对象想象成一个二进制字节缓存区 array buffer 的 “解释器” —— 它知道如何在读取或写入时正确地转换字节码。这意味着它能在二进制层面处理整数与浮点转化、字节顺序等其他有关的细节问题。
「DataView 使用示例」
const buffer = new ArrayBuffer(16);
// Create a couple of views
const view1 = new DataView(buffer);
const view2 = new DataView(buffer, 12, 4); //from byte 12 for the next 4 bytes
view1.setInt8(12, 42); // put 42 in slot 12
console.log(view2.getInt8(0)); // expected output: 42
DataView 方法
对象提供了 getInt8()、getUint8()、setInt8() 和 setUint8() 等方法来操作数据。具体每个方法的使用,我们就不详细介绍。这里我们来看个简单的例子:
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer, 0);
view.setInt8(1, 68);
view.getInt8(1); // 68