JS的二进制家族:ArrayBuffer的具体介绍

简介: ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer 不能直接操作,而是要通过类型数组对象 或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。

一、基础知识


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))
}


相关文章
|
6月前
|
前端开发 JavaScript 数据安全/隐私保护
JavaScript 中的二进制散列值和权限设计
这篇文章介绍了JavaScript中使用位运算符进行权限控制的方法。文章首先介绍了JavaScript中的进制类型,包括十进制、二进制、十六进制和八进制。然后解释了位运算符的概念和常用的按位与、按位或、按位异或和按位非操作符。接下来讨论了位运算符在传统权限系统中的应用场景,并给出了一个基于二进制变量表示权限的示例。最后,文章提到了位运算符方案的局限性,例如每个权限码必须是唯一且只有一位为1的限制。但总的来说,在中小型业务中可以使用这种方式进行权限控制。
|
3月前
|
JavaScript 前端开发
JS二进制转10进制、十六进制
JS二进制转10进制、十六进制 【8月更文挑战第9天】
125 6
|
3月前
|
JavaScript 前端开发 开发者
js二进制及其相关转换全总结
【8月更文挑战第9天】js二进制及其相关转换全总结
121 5
|
6月前
|
JavaScript 前端开发 数据处理
掌握JavaScript中的二进制运算,提升你的编程技能!
掌握JavaScript中的二进制运算,提升你的编程技能!
|
6月前
|
存储 自然语言处理 前端开发
详谈JavaScript 二进制家族:Blob、File、FileReader、ArrayBuffer、Base64
详谈JavaScript 二进制家族:Blob、File、FileReader、ArrayBuffer、Base64
240 1
|
6月前
|
算法 JavaScript
JS算法-颠倒二进制位
JS算法-颠倒二进制位
|
6月前
|
存储 移动开发 自然语言处理
谈谈JS二进制:File、Blob、FileReader、ArrayBuffer、Base64(下)
谈谈JS二进制:File、Blob、FileReader、ArrayBuffer、Base64(下)
123 0
|
4月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
97 2
|
4月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
130 4
|
4月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的宠物援助平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的宠物援助平台附带文章源码部署视频讲解等
82 4