JS中的File(二):TypedArray和ArrayBuffer详解

目录

一、TypedArray

1、定义

2、注意事项

二、ArrayBuffer

1、定义和构造

2、属性

3、方法

4、使用意义

三、Blob、TypedArray和ArrayBuffer的互相转换

1、websocket接收arrayBuffer

2、blob转arrayBuffer

3、arrayBuffer to Blob

4、ArrayBuffer to Uint8数组(8位(1字节大小)的无符号整数数组)

5、Uint8 to ArrayBuffer

6、Array/ArrayBuffer to Blob

7、获取/设置ArrayBuffer对应的数值(使用TypedArray作为视图来进行修改)

8、TypedArray 和 Array互转


一、TypedArray

1、定义

TypedArray是描述表达二进制数据的一种类数组数据视图,但并没有一个叫TypedArray的直接构造器。所以,属于TypedArray的子类有以下,其均可用于构造以及相关的类数组操作

JS中的File(二):TypedArray和ArrayBuffer详解_第1张图片

2、注意事项

注意,TypedArray既然是类数组,就具有类数组的相关特性,比如可以读取length、按索引读取、切片读取等等方法,但是不可以使用 push 或者 pop函数【JS中的类数组有函数中的隐式传参arguments浏览器中节点NodeList字符串StringTypedArray

二、ArrayBuffer

1、定义和构造

ArrayBuffer对象用来表示通用的原始二进制数据缓冲区。它是一个字节数组,是一个可转移对象(Transferable Object),但是它不可以直接操作其中的内容,而是要通过转换为TypedArray或者DataView(一种对象视图接口)再来进行读写操作

构造函数的形式

new ArrayBuffer(length, options)

length代表数组缓冲区的大小(以字节为单位),options 代表一个对象,包含属性maxByteLength即数组缓冲区可以调整到的最大大小(以字节为单位

返回的ArrayBuffer对象中内容初始化为0

【大小最好不超过1GB,减少内存溢出的风险】

2、属性

  • byteLength:返回数组缓冲区的长度

  • detached:访问器,看是否将该实例从底层内存中分离,即转移实例

const buffer = new ArrayBuffer(8);
console.log(buffer.detached); // false,未转移实例
const newBuffer = buffer.transfer();
console.log(buffer.detached); // true,转移后的旧实例detached
console.log(newBuffer.detached); // false
  • maxByteLength :返回该数组缓冲区可调整到的最大长度
  • resizable:表示数组缓冲区是否可以调整大小。当设置了maxByteLength就代表可以调整大小
const buffer1 = new ArrayBuffer(8, { maxByteLength: 16 });
const buffer2 = new ArrayBuffer(8);

console.log(buffer1.resizable);
// Expected output: true

console.log(buffer2.resizable);
// Expected output: false

3、方法

  • isView:是否未ArrayBuffer的可用视图,例如TypedArray或DataView
ArrayBuffer.isView(); // false
ArrayBuffer.isView([]); // false
ArrayBuffer.isView({}); // false
ArrayBuffer.isView(null); // false
ArrayBuffer.isView(undefined); // false
ArrayBuffer.isView(new ArrayBuffer(10)); // false

ArrayBuffer.isView(new Uint8Array()); // true
ArrayBuffer.isView(new Float32Array()); // true
ArrayBuffer.isView(new Int8Array(10).subarray(0, 3)); // true

const buffer = new ArrayBuffer(2);
const dv = new DataView(buffer);
ArrayBuffer.isView(dv); // true
  • resize():设置了maxByteLength之后,resize这个buffer的大小
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });

console.log(buffer.byteLength);
// Expected output: 8

buffer.resize(12);

console.log(buffer.byteLength);
// Expected output: 12
  • 其他方法,slice()、transfer()等

4、使用意义

ArrayBuffer存在的意义是方便开发人员可以直接对自动内存进行管理。

例如,在JS中创建变量时,引擎会去计算当前这是什么类型的变量以及如何在内存中表示它。因为计算的过程需要耗费时间及内存空间,JS引擎通常会保留比变量真正需要的空间更多的空间。而且由于变量的不同,内存所消耗的空间可能比需要的大2到8倍,这可能导致大量的内存浪费。

此外,某些创建和使用JS对象的模式会使垃圾的回收变得非常困难。如果您正在执行手动内存管理,可以按需选择一种适合您的用例分配和取消分配策略

三、Blob、TypedArray和ArrayBuffer的互相转换

转换关系总结:

 Blob <-> ArrayBuffer <-> TypeArray <—-> Array

1、websocket接收arrayBuffer

/* websocket的情况下二进制流的获取 */
var svip = 'ws://127.0.0.1:8080';
var ws = new WebSocket(svip);
ws.binaryType = 'arraybuffer'
ws.onmessage = function (e) {
	var message = e.data;
}

2、blob转arrayBuffer

var bl = new Blob(); // bl是要转换的blob
var fr = new FileReader();
fr.onload = function(){
	var ab = this.result; // ab是转换后的结果
}
fr.readAsArrayBuffer(bl); //用reader,以arrayBuffer的形式读出

3、arrayBuffer to Blob

var ab = new ArrayBuffer(32);
var blob = new Blob([ab]); // 注意必须包裹[]

4、ArrayBuffer to Uint8数组(8位(1字节大小)的无符号整数数组)

var ab = arrayBuffer; // arrayBuffer为要转换的值
var u8 = new Uint8Array(ab);

5、Uint8 to ArrayBuffer

typedArray中的buffer通过.buffer属性获取

var u8 = new Uint8Array();
var ab = u8.buffer; // ab即是u8对应的arrayBuffer

6、Array/ArrayBuffer to Blob

这样转换出来的数组,可以让Blob中的文件内容进行正常的读写操作

var arr = [0x01,0x02,0x00,0x00,0x00,0x00,0x03];
var u8 = new Uint8Array(arr);
var blob=new Blob([u8],{type:'image/png'})

7、获取/设置ArrayBuffer对应的数值(使用TypedArray作为视图来进行修改)

一串ArrayBuffer是可以被“理解”为很多个值的,以下面这个值为例,

按照服务端的协议,这串数据流的格式如下:
1 unsign byte (1字节) + 1 unsign int (4字节) + 1 unsign short (2字节)

解析方法如下,注意buffer中解析起点的索引符合TypedArray的读写大小单位

var arr = [0x01,0x02,0x00,0x00,0x00,0x00,0x03];
var u8 = new Uint8Array(arr);
var ab = u8.buffer;
console.log(ab); // ab为要解析的ArrayBuffer
var u8 = new Uint8Array(ab, 0, 1); // (arraybuffer, 字节解析的起点, 解析的长度)
var val_byte = u8[0];
console.log(val_byte);
// 解析unsign int
// 由于Uint32Array的解析起点必须是4的整数倍,而在流中该数据的起点是1,所以选择先“裁剪”(slice)出要解析的流片段,再用Uint32去解析该片段
var u32buff = ab.slice(1, 5);
var u32 = new Uint32Array(u32buff);
var val_uint = u32[0];
console.log(val_uint);
// 解析unsign short
var u16buff = ab.slice(5, 7);
var u16 = new Uint16Array(u16buff);
var val_short = u16[0];
console.log(val_short);

8、TypedArray 和 Array互转

可以用Array.from或者TypedArray.from实现互转

你可能感兴趣的:(JavaScript学习笔记,javascript,开发语言,ecmascript)