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

1.ArrayBuffer是什么?

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

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

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

1.特点

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

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

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

2. 属性

1.byteLength

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

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

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

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

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

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

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

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

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

3.字节序

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

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

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

例如:

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

ps:判断字节序的方法

  1. const BIG_ENDIAN = Symbol('BIG_ENDIAN');
  2. const LITTLE_ENDIAN = Symbol('LITTLE_ENDIAN');
  3.  
  4. function getPlatformEndianness() {
  5. let arr32 = Uint32Array.of(0x12345678);
  6. let arr8 = new Uint8Array(arr32.buffer);
  7. switch ((arr8[0]*0x1000000) + (arr8[1]*0x10000) + (arr8[2]*0x100) + (arr8[3])) {
  8. case 0x12345678:
  9. return BIG_ENDIAN;
  10. case 0x78563412:
  11. return LITTLE_ENDIAN;
  12. default:
  13. throw new Error('Unknown endianness');
  14. }
  15. }

4.buffer和字符串互相转化

  1. /**
  2. * Convert ArrayBuffer/TypedArray to String via TextDecoder
  3. *
  4. * @see https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder
  5. */
  6. function ab2str(
  7. input: ArrayBuffer | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array,
  8. outputEncoding: string = 'utf8',
  9. ): string {
  10. const decoder = new TextDecoder(outputEncoding)
  11. return decoder.decode(input)
  12. }
  13.  
  14. /**
  15. * Convert String to ArrayBuffer via TextEncoder
  16. *
  17. * @see https://developer.mozilla.org/zh-CN/docs/Web/API/TextEncoder
  18. */
  19. function str2ab(input: string): ArrayBuffer {
  20. const view = str2Uint8Array(input)
  21. return view.buffer
  22. }
  23.  
  24. /** Convert String to Uint8Array */
  25. function str2Uint8Array(input: string): Uint8Array {
  26. const encoder = new TextEncoder()
  27. const view = encoder.encode(input)
  28. return view
  29. }

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 溢出规则

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

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

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

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

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

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

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

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

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

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

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

  1. const view16 = new Uint16Array([1,1000]); // 创建一个和数组同长度的视图数组
  2. const view8 = new Uint8Array(view16); // view8创建一个同样长度的视图数组,并将值copy过来
  3. console.log(view8[0]); //
  4. console.log(view8[1]); //
  5. // 1000大于255,需要对溢出的值进行截取;
  6. // (1000).toString(2) === "1111101000"
  7. // view8只能取最右侧8位,parseInt(11101000, 2) === 232
  8.  
  9. // 另外,上面view8,view16操作 。,,的底层buffer是两个,因为不传入buffer,就会自动创建buffer
  10. // 如果想要操作一个buffer, 需要将buffer传入
  11. const newView8 = new Uint8Array(view16.buffer);
  12. view16[0] = 123;
  13. console.log(view16.buffer);
  14. console.log(view16); // [123,1000]
  15. console.log(newView8); // [123, 0, 232, 3]
  16. console.log(view8[0]); //
  17. console.log(newView8[0]); //

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

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

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

3.属性

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

4.方法

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

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

除此之外还有:

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

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

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

  类似slice()[begin, end)

  1. console.log(view16); // [0,0,1,2,3,4,0,0,0,0];
  2. const newView = view16.subarray(3,4)
  3. console.log(newView); // [2]
  • of()---静态方法

  1. Uint8Array.of(1,2,3)
  2. // 相当于
  3. new Uint8Array([1,2,3])
  • from(arr, [fun])---静态方法
  1. // 1.转为实例
  2. Uint8Array.from([1,3])
  3. // 2. 使用第二个参数方法
  4. Int8Array.of(127, 126, 125).map(x => 2 * x)
  5. // Int8Array [ -2, -4, -6 ]
  6.  
  7. Int16Array.from(Int8Array.of(127, 126, 125), x => 2 * x)
  8. // Int16Array [ 254, 252, 250 ]

2.DataView对象

1.基础信息

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

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

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

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

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

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

  1. const buffer = (new Uint8Array([255,255,253,252])).buffer;
  2. const dataView = new DataView(buffer);
  3. console.log(dataView.getUint8(0)); //
  4. console.log(dataView.getUint16(0)); //
  5. dataView.setUint32(0,0);
  6. console.log(dataView.getUint32(0)); //

2. 属性

  • buffer
  • byteLength
  • byteOffset

3.方法

get方法8种:

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

set方法8种:

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

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

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

3. 应用

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

  1. ES6 二进制数组

    二进制数组(ArrayBuffer对象.TypedArray视图和DataView视图)是JavaScript操作二进制数据的一个接口.这些对象早就存在,属于独立的规格(2011年2月发布),ES6将 ...

  2. es6二进制数组--基础

    一.概念二进制数组由 ArrayBuffer对象 TypeArray 视图和DataView视图 三部分组成是javascript操作二进制数据的一个接口. 早在2011年2月就已经发布,但是由于ES ...

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

    在项目开发中,使用SQL Server存储数据,数据类型image可以保存图片.但是在存储之前需要将图片转化为二进制数组的形式进行赋值. 将图片文件转换为二进制数组 /// <summary&g ...

  4. 【C#基础】byte二进制数组转string

    //解析post请求数组返回的数组 //解码返回的二进制数组 public string DecodeBytes(byte[] c) { string html = string.Empty; try ...

  5. Buffer、ArrayBuffer、DataView互转(node.js)

    1.Buffer转ArrayBuffer // 实例一 const buf = Buffer.from("this is a test"); console.log(buf); c ...

  6. java 图片Base64字符串转图片二进制数组

    public static byte[] base64ToImgByteArray(String base64) throws IOException{ sun.misc.BASE64Decoder ...

  7. 二进制数组-ArrayBuffer对象

    ArrayBuffer对象:存储二进制数据的一段内存,不能写/读 ,类似数组的对象 只能通过TypedArray视图/DataView视图 读/写 va buf = new ArrayBuffer(3 ...

  8. JavaScript类型化数组(二进制数组)

    0.前言 对于前端程序员来说,平时很少和二进制数据打交道,所以基本上用不到ArrayBuffer,大家对它很陌生,但是在使用WebGL的时候,ArrayBuffer无处不在.浏览器通过WebGL和显卡 ...

  9. js 的 ArrayBuffer 和 dataView

    arrayBuffer文档 一个十六进制代表4位,0xF = 1111,0xFF = 1111 1111,八位是1字节,所以通常用两个16进制代表1字节. 假如我申请一个8字节的内存空间,然后初始化为 ...

随机推荐

  1. PHP切割整数工具,类似微信红包金额分配

    Composer地址:https://packagist.org/packages/werbenhu/php-number-slicing GitHub地址:https://github.com/we ...

  2. SAS学习笔记46 宏变量的可使用范围

    全局宏变量 在宏程序内部,除了使用%GLOBAL语句创建.在某些情况下,还可以直接使用DATA步中的CALL SYMPUT创建. 在一个宏程序中,在包含CALL SYMPUT的DATA步程序之前,如果 ...

  3. java之集合那些事

    集合概述: 集合和数组都可以保存多个对象,但是数组的长度不可变,集合可以保存数量变化的数据.java中的集合类主要由两个接口派生出,Collection和Map Collection接口和Iterat ...

  4. HTML中关于动态创建的标签无法绑定js事件的解决方法:.on()方法的 [.selector]

    在前端页面的时候,会经常遇到用JavaScript动态创建出来的Button按钮或其他标签无法使用点击事件的问题.如下代码,使用jquery在body中动态创建一个class为demo的Button按 ...

  5. mybaits实现oracle批量新增数据,回填主键

    项目有需求,百度了很久,反正他们说的方法,我都没成功,我也不知道是不是我写代码的姿势不正确,没办法只能自己想法子了 我们这个项目用到了通过Mapper,通用Mapper里通过OracleProvide ...

  6. SQL Server中语句的自动参数化

    原文:SQL Server中语句的自动参数化 use master go if exists(select * from sys.databases where name = 'test') drop ...

  7. .NET Core使用swagger遇到的坑

    今天突然点开写好的接口,突然发现展开时同时展开了两个接口.如图 我点这两个接口任意一个,这两个都会同时展开或折叠. 原因是他们actinName相同,虽然在vs里面只要http方法不同,action是 ...

  8. ligerui.grid.extend.rowSpan

    扩展LigerUI的Grid中的相同列合并行功能,代码如下:$.extend($.ligerui.controls.Grid.prototype, { _getHtmlFromData:functio ...

  9. 关于Vue中,在方法中使用(操作)子组件获取到的数据

    已知,子组件通过props获取父组件传过来的数据,而这个数据是无法在created.mounted生命周期中使用的,只能在beforeUpdated或者updated获取到: 但是如果我们要使用这个数 ...

  10. For... in 及 For… of 及 forEach

    For... in 及 For… of let arr = ["a","b"]; for (let a in arr) { console.log(a) // ...