ArrayBuffer、TypedArray、DataView二进制数组

三个是处理二进制数据的接口。都是类数组。

1.ArrayBuffer是什么?

ArrayBuffer是一个二进制对象(文件,图片等)。它指向固定长度的,连续的内存区域。

const buffer = new ArrayBuffer(16);
// buffer.byteLength === 16 生成16位字节的二进制数据,每一位都默认是0

上面分配了一个长度为16个字节的内存区域,代表16byte的二进制数据。并且默认每bit内容都是0。

1.特点

1)和数组不同,它创建后长度就固定了,不能增删。

2)它实实在在占用了内存那么多空间。

3)不能直接访问里面的数据,需要通过另外的类型数组对象(TypedArray类型)来访问。

2. 属性

1.byteLength

获取分配的内存区域buffer的字节长度。

2.slice(start, end)--实例方法

ArrayBuffer对象唯一一个可以操作内存的方法。

        const buffer = new ArrayBuffer(12);
        const view = new Uint8Array(buffer);
        view[0] = 1; // [1,0,0,....0]
        const newBuffer = buffer.slice(0,3); // [0,3)
        const newView = new Uint8Array(newBuffer);
        console.log(newView); //[1,0,0]

1)先分配一段新内存,脱离原来的内存

2)将原来内存中和这段新内存对应的部分的buffer内容拷贝过来

3.isView(param)---静态方法

判断参数是否为该ArrayBuffer的视图实例。

        const buffer = new ArrayBuffer(12);
        const view = new Uint8Array(buffer);
        console.log(ArrayBuffer.isView(view)); // true

3.字节序

ArrayBuffer中的字节存储顺序,是按照小端字节序(little endian);意思是重要字节顺序往后排。

??重要字节意思是:权重越大越重要,百位比十位重要,十位比各位重要

与之相对应的是大端字节序(big endian);意思是重要的字节顺序排前面。

例如:

        const view32 = new Uint32Array([1,1000]);
        const view16 = new Uint16Array(view32.buffer);
        console.log(view32); // [1,1000]
        // [1,1000]都是32位的四字节
        // 1--转16位相当于前16位0, 后16位1
        // 1000--转16位相当于前16位0, 后16位1000
        console.log(view16) // [1,0,1000,0]

ps:判断字节序的方法

const BIG_ENDIAN = Symbol(‘BIG_ENDIAN‘);
const LITTLE_ENDIAN = Symbol(‘LITTLE_ENDIAN‘);

function getPlatformEndianness() {
  let arr32 = Uint32Array.of(0x12345678);
  let arr8 = new Uint8Array(arr32.buffer);
  switch ((arr8[0]*0x1000000) + (arr8[1]*0x10000) + (arr8[2]*0x100) + (arr8[3])) {
    case 0x12345678:
      return BIG_ENDIAN;
    case 0x78563412:
      return LITTLE_ENDIAN;
    default:
      throw new Error(‘Unknown endianness‘);
  }
}

4.buffer和字符串互相转化

/**
 * Convert ArrayBuffer/TypedArray to String via TextDecoder
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder
 */
function ab2str(
  input: ArrayBuffer | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array,
  outputEncoding: string = ‘utf8‘,
): string {
  const decoder = new TextDecoder(outputEncoding)
  return decoder.decode(input)
}

/**
 * Convert String to ArrayBuffer via TextEncoder
 *
 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/TextEncoder
 */
function str2ab(input: string): ArrayBuffer {
  const view = str2Uint8Array(input)
  return view.buffer
}

/** Convert String to Uint8Array */
function str2Uint8Array(input: string): Uint8Array {
  const encoder = new TextEncoder()
  const view = encoder.encode(input)
  return view
}

2.视图类对象:

视图对象自己本身不存储任何东西。它是一个访问内存中数据的工具。同一段内存,不同的访问会得到不同的数据。

类型数组对象可以分为两种,一种是TypedArray,一种是DataView

1.TypedArray类型数组对象

它是一个统称,不是具体的对象。它创建后的数值的类型就固定了。

1. 分类如下:

  • Uint8Array, Uint16Array, Uint32Array---分别是8位,16位,32位的无符号整数。
  • Uint8ClampedArray:---8位整数,但是溢出时处理逻辑不同。(超出255的全部按255,低于0的全部按0,适用于处理图像)
  • Int8Array,Int16Array,Int32Array---8位,16位,32位有符号整数。可能是负数。
  • Float32Array, Float64Array---32位,64位的浮点数。

其中对于第一类简单解释如下:

  1. Uint8Array将内存中的每个字节当成一个整数,值大小范围为0-255;
  2. Uint16Array将内存中每两个字节当成一个整数,值范围大小为0-65535;
  3. Uint32Array将内存中每四个字节当成一个整数,值范围大小为0-4294967295;

PS 溢出规则

正向溢出(overflow):当输入值大于当前数据类型的最大值,结果等于当前数据类型的最小值加上余值,再减去 1。
负向溢出(underflow):当输入值小于当前数据类型的最小值,结果等于当前数据类型的最大值减去余值的绝对值,再加上 1。

2.类型数组对象的用法如下:

如果不传入buffer,会自动创建ArrayBuffer,然后通过TypedArray的buffer属性访问。因为类型数组对象依赖ArrayBuffer存在,否则毫无意义。

1. new TypedArray(buffer, [byteoffset], [length])

 其中buffer为传入的内存空间; byteoffset默认是0,为查看内存视图的开始位置; length为查看的长度,默认到最后一个元素。

??如果是Uint16Array,byteoffset必须是2的倍数,同理Uint32Array的必须是4的倍数

如果想任意位置开始,可以使用DataView

        const buffer = new ArrayBuffer(16);
        console.log(buffer.byteLength); // 分配内存的大小 16
        // 下面表示从索引2开始取5个整数的长度
        const view16 = new Uint16Array(buffer,2,5);
        console.log(view16.length); // 数字的长度

2. new TypedArray(object); --传入数组或者类数组.

        const view8 = new Uint8Array([1,2,3,4]); // 分配一个新的内存,不同于原来的数组的内存
        const view8Buffer = view8.buffer;
        console.log(view8.length); // 4
        console.log(view8Buffer.byteLength); // 4
       // 因为类数组,可以[...view8]还原成数组

3.new TypedArray(typedArray)--将类型数组对象当参数传入

        const view16 = new Uint16Array([1,1000]); // 创建一个和数组同长度的视图数组
        const view8 = new Uint8Array(view16); // view8创建一个同样长度的视图数组,并将值copy过来
        console.log(view8[0]); // 1
        console.log(view8[1]); // 232
        // 1000大于255,需要对溢出的值进行截取;
        // (1000).toString(2) === "1111101000"
        // view8只能取最右侧8位,parseInt(11101000, 2) === 232

        // 另外,上面view8,view16操作 。,,的底层buffer是两个,因为不传入buffer,就会自动创建buffer
        // 如果想要操作一个buffer, 需要将buffer传入
        const newView8 = new Uint8Array(view16.buffer);
        view16[0] = 123;
        console.log(view16.buffer);
        console.log(view16); // [123,1000]
        console.log(newView8); // [123, 0, 232, 3]
        console.log(view8[0]); // 1
        console.log(newView8[0]); // 123

4. new TypedArray(length)--创建一个length长度的类型数组

        const view16 = new Uint16Array(4);
        const viewBuffer = view16.buffer;
        console.log(view16.length); // 4
        console.log(viewBuffer.byteLength); // 4*2=8
        console.log(view16[0]); // 0

5. new TypedArray() --创建一个长度为0的类型数组

3.属性

  • BYTES_PER_ELEMENT: 每个数据所占的字节数
        const view16 = new Uint16Array(view32.buffer);
        console.log(view16.BYTES_PER_ELEMENT);  //2
  • buffer: 返回视图对应的ArrayBuffer对象
  • byteLength: 字节的长度
  • length是数据的长度
  • byteOffset:从buffer读取数据的开始位置

4.方法

可以使用数组的查询遍历类方法:如map,slice, find, reduce等;

不可以使用数组的方法: 如splice, concat;

除此之外还有:

  • arr.set(formArr, [offset])--代替实现原来的concat方法。

将fromArr的值写入,从arr的offset开始写入

        const view16 = new Uint16Array(10);
        const view8 = new Uint8Array([1,2,3,4]);
        view16.set(view8,2); // 表示从view16的索引为2开始,把view8的内容复写到view16中
        // 所以view8的长度+length必须不大于view16的长度
        console.log(view16); // [0,0,1,2,3,4,0,0,0,0];
  • arr.subarray([begin, end])--创建一个新的视图,值是原来数组截取的部分值;

  类似slice()[begin, end)

        console.log(view16); // [0,0,1,2,3,4,0,0,0,0];
        const newView = view16.subarray(3,4)
        console.log(newView); // [2]
  • of()---静态方法
Uint8Array.of(1,2,3)
// 相当于
new Uint8Array([1,2,3])
  • from(arr, [fun])---静态方法
// 1.转为实例
Uint8Array.from([1,3])
// 2. 使用第二个参数方法
Int8Array.of(127, 126, 125).map(x => 2 * x)
// Int8Array [ -2, -4, -6 ]

Int16Array.from(Int8Array.of(127, 126, 125), x => 2 * x)
// Int16Array [ 254, 252, 250 ]

2.DataView对象

1.基础信息

是一个超级灵活和“无类型”的视图。它允许以任意offset(偏移量)访问任意类型的数组。

也可以自定义复合类型的视图。可以自定义字节序(处理网络设备传递的数据,可能是大字节序)。

不同于TypedArray的构造函数调用就决定了数据类型,DataView是调用方法的时候决定数据类型,如.getUint8(i)等;

支持8种数据存取,除了Uint8ClampsArray不支持,其他TypedArray的的类型都支持

new DataView(buffer, [byteoffset], [bytelength])

不同于TypedArray可以自行创建buffer, DataView要求必须传入buffer。

        const buffer = (new Uint8Array([255,255,253,252])).buffer;
        const dataView = new DataView(buffer);
        console.log(dataView.getUint8(0)); // 255
        console.log(dataView.getUint16(0)); // 65535
        dataView.setUint32(0,0);
        console.log(dataView.getUint32(0)); // 0

2. 属性

  • buffer
  • byteLength
  • byteOffset

3.方法

get方法8种:

getInt8:读取 1 个字节,返回一个 8 位整数。
getUint8:读取 1 个字节,返回一个无符号的 8 位整数。
getInt16:读取 2 个字节,返回一个 16 位整数。
getUint16:读取 2 个字节,返回一个无符号的 16 位整数。
getInt32:读取 4 个字节,返回一个 32 位整数。
getUint32:读取 4 个字节,返回一个无符号的 32 位整数。
getFloat32:读取 4 个字节,返回一个 32 位浮点数。
getFloat64:读取 8 个字节,返回一个 64 位浮点数。

set方法8种:

setInt8:写入 1 个字节的 8 位整数。
setUint8:写入 1 个字节的 8 位无符号整数。
setInt16:写入 2 个字节的 16 位整数。
setUint16:写入 2 个字节的 16 位无符号整数。
setInt32:写入 4 个字节的 32 位整数。
setUint32:写入 4 个字节的 32 位无符号整数。
setFloat32:写入 4 个字节的 32 位浮点数。
setFloat64:写入 8 个字节的 64 位浮点数。

set方法可以传递第三个参数,true表示小端字节序写入;false表示大端字节序写入。

// 判断当前计算机的字节序
const littleEndian = (function() {
  const buffer = new ArrayBuffer(2);
  new DataView(buffer).setInt16(0, 256, true);
  return new Int16Array(buffer)[0] === 256;
})(); // true表示小端

3. 应用

原文地址:https://www.cnblogs.com/lyraLee/p/11595255.html

时间: 2024-10-09 07:03:36

ArrayBuffer、TypedArray、DataView二进制数组的相关文章

二进制数组

前面的话 二进制数组(ArrayBuffer对象.TypedArray视图和DataView视图)是javascript操作二进制数据的一个接口.这些对象早就存在,属于独立的规格(2011年2月发布),ES6将它们纳入了ECMAScript规格,并且增加了新的方法.本文将详细介绍二进制数组 引入 二进制数组的原始设计目的,与WebGL项目有关.所谓WebGL,就是指浏览器与显卡之间的通信接口,为了满足javascript与显卡之间大量的.实时的数据交换,它们之间的数据通信必须是二进制的,而不能是

es6二进制数组--基础

一.概念二进制数组由 ArrayBuffer对象 TypeArray 视图和DataView视图 三部分组成是javascript操作二进制数据的一个接口. 早在2011年2月就已经发布,但是由于ES6 的出现,将这些对象添加了一些新的方法.它是一种类似C语言中直接操作字节的机制. 产生背景这个接口的原始设计目的,与WebGL项目有关.所谓WebGL,就是指浏览器与显卡之间的通信接口,为了满足JavaScript与显卡之间大量的.实时的数据交换,它们之间的数据通信必须是二进制的,而不能是传统的文

js二进制数组创建注意点

js二进制数组创建注意点:关于二进制数组的更多内容可以参阅ES2015 TypedArray视图一章节.可以通过ArrayBuffer对象分配内存,然后再建立视图.视图也可以不通过ArrayBuffer对象,直接分配内存而生成,代码实例如下: var view16 = new Int16Array(2); view16[0] = 1; view16[1] = 2; console.log(view16[1]); 但是你不能够通过下面的方式来创建: var view16 = new Int16Ar

C#中将图片文件转化为二进制数组-用于数据库存储

在项目开发中,使用SQL Server存储数据,数据类型image可以保存图片.但是在存储之前需要将图片转化为二进制数组的形式进行赋值. 将图片文件转换为二进制数组 /// <summary> /// 将图片文件转换为二进制数组 /// </summary> /// <param name=”picpath”>图片路径</param> /// <returns>二进制数组</returns> private byte[] GetBin

node随笔-二进制数组buffer

Buffer简介 在 ECMAScript 2015 (ES6) 引入 TypedArray 之前,JavaScript 语言没有读取或操作二进制数据流的机制. Buffer 类被引入作为 Node.js API 的一部分,使其可以在 TCP 流或文件系统操作等场景中处理二进制数据流. TypedArray 现已被添加进 ES6 中,Buffer 类以一种更优化.更适合 Node.js 用例的方式实现了 Uint8Array API. Buffer 类的实例类似于整数数组,但 Buffer 的大

序列化保存为二进制数组 忘得干干净净

ReturnExam re = new ReturnExam(); re.Juquest = jseleqj; re.Muliselectquest = mseleqj; re.Selectquest = seleqj; re.Tiankongquest = tseleqj; re.Wendaquest = wseleqj; MemoryStream stream = new MemoryStream(); BinaryFormatter binFormat = new BinaryFormat

ArrayBuffer和TypedArray,以及Blob的使用

前端使用TypedArray编辑二进制 ES6提供了, ArrayBuffer和TypedArray, 让前端也可以直接操作编辑二进制数据, 网页中的类型为file的input标签, 也可以通过FileReader转化为二进制, 然后再做编辑等, 本文提供参考: ArrayBuffer : 代表内存之中的一段二进制数据, 通过它我们可以直接创建二进制对象,然后使用相关的方法和属性. 如何使用ArrayBuffer: new ArrayBuffer(32), 从内存中申请32个字节: 把Array

JavaScript二进制数据序列化和反序列化

最近业余时间在搞h5小游戏,由于同步协议过于频繁,和服务器之间的同步直接用json就显得太浪费了,于是我们商讨之下决定改用二进制.学习过程中并没有遇到一篇就解决问题的文章,遂再总结一发. 1.二进制数据的存储 ArrayBuffer对象.TypedArray对象.DataView对象是JavaScript操作二进制数据的一个接口. (1)ArrayBuffer对象:代表内存之中的一段二进制数据,它不能直接读写,只能通过视图(TypedArray视图和DataView视图)来读写,视图的作用是以指

nodeJS之二进制buffer对象

前面的话 在ES6引入TypedArray之前,JavaScript语言没有读取或操作二进制数据流的机制.Buffer类被引入作为Nodejs的API的一部分,使其可以在TCP流和文件系统操作等场景中处理二进制数据流.现在TypedArray已经被添加进ES6中,Buffer类以一种更优与更适合Node.js用例的方式实现了Uint8Array.本文将详细介绍buffer对象 概述 由于应用场景不同,在Node中,应用需要处理网络协议.操作数据库.处理图片.接收上传文件等,在网络流和文件的操作中