一、基础知识
1.1 ArrayBuffer
ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer 不能直接操作,而是要通过类型数组对象 或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。
ArrayBuffer 简单说是一片内存,但是你不能直接用它。这就好比你在 C 里面,malloc 一片内存出来,你也会把它转换成 unsigned_int32 或者 int16 这些你需要的实际类型的数组/指针来用。
这就是 JS 里的 TypedArray 的作用,那些 Uint32Array 也好,Int16Array 也好,都是给 ArrayBuffer 提供了一个 “View”,MDN 上的原话叫做 “Multiple views on the same data”,对它们进行下标读写,最终都会反应到它所建立在的 ArrayBuffer 之上。
语法
new ArrayBuffer(length)
- 参数:length 表示要创建的 ArrayBuffer 的大小,单位为字节。
- 返回值:一个指定大小的 ArrayBuffer 对象,其内容被初始化为 0。
- 异常:如果 length 大于
Number.MAX_SAFE_INTEGER
(>= 2 ** 53)或为负数,则抛出一个RangeError
异常。
示例
下面的例子创建了一个 8 字节的缓冲区,并使用一个 Int32Array
来引用它:
let buffer = new ArrayBuffer(8); let view = new Int32Array(buffer);
从 ECMAScript 2015 开始,ArrayBuffer
对象需要用 new
运算符创建。如果调用构造函数时没有使用 new
,将会抛出 TypeError
异常。比如执行该语句 let ab = ArrayBuffer(10)
将会抛出以下异常:
VM109:1 Uncaught TypeError: Constructor ArrayBuffer requires 'new' at ArrayBuffer (<anonymous>) at <anonymous>:1:10
对于一些常用的 Web API,如 FileReader API 和 Fetch API 底层也是支持 ArrayBuffer,这里我们以 FileReader API 为例,看一下如何把 File 对象读取为 ArrayBuffer 对象:
const reader = new FileReader(); reader.onload = function(e) { let arrayBuffer = reader.result; } reader.readAsArrayBuffer(file);
1.2 Unit8Array
Uint8Array 数组类型表示一个 8 位无符号整型数组,创建时内容被初始化为 0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。
语法
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); // new TypedArray(object); // 当传入一个 object 作为参数时,就像通过 TypedArray.from() // 方法创建一个新的类型化数组一样。 var iterable = function*(){ yield* [1,2,3]; }(); var uint8 = new Uint8Array(iterable); // Uint8Array[1, 2, 3]
通过ArrayBuffer的格式读取本地数据
document.getElementById('f').addEventListener('change', function (e) { const file = this.files[0]; const fileReader = new FileReader(); fileReader.onload = function () { const result = fileReader.result; console.log(result) } fileReader.readAsArrayBuffer(file); }, false);
通过ArrayBuffer的格式读取Ajax请求数据
- 通过xhr.responseType = "arraybuffer" 指定响应的数据类型
- 在onload回调里打印xhr.response
前端
const xhr = new XMLHttpRequest(); xhr.open("GET", "ajax", true); xhr.responseType = "arraybuffer"; xhr.onload = function () { console.log(xhr.response) } xhr.send();
Node端
const app = new Koa(); app.use(async (ctx) => { if (pathname = '/ajax') { ctx.body = 'hello world'; ctx.status = 200; } }).listen(3000)
ArrayBuffer转json
ws.onmessage = function (evt) { // evt.data是ArrayBuffer // 将其转换为uint8字节流 var uint8_msg = new Uint8Array(evt.data); // 解码成字符串 var decodedString = String.fromCharCode.apply(null, uint8_msg); console.log(decodedString); // parse,转成json数据 var data = JSON.parse(decodedString); console.log(data); };
另一种方法,utf-8
防止乱码
let content = file.data;//arraybuffer类型数据 let resBlob = new Blob([content]) let reader = new FileReader() reader.readAsText(resBlob, "utf-8") reader.onload = () => { let res = JSON.parse(reader.result) console.log(JSON.parse(reader.result)) }