[HTML5] ArrayBuffer与类型化数组

时间:2023-01-18 09:08:26

写在前面

这是关于JS二进制操作的第三篇博客,前两篇详见:

[HTML5] Blob对象

[HTML5] FileReader对象

此前从宏观角度介绍了如何通过JS创建一个二进制对象,并介绍了如何将本地二进制内容读取至内存。本篇将介绍如何在内存中操作二进制数据。

JS与二进制数据

现代计算机中操作二进制数据的基本单位是字节(byte),故二进制数据一般以字节数组的形式存在于程序中。如:Java中的InputStream于OutputStream类,允许通过指定大小的字节数组(如:byte[] bytes = new byte[1024])对文件进行读写。

然而回到JS,其设计之初也没有想过要处理二进制,故对于字节的概念并不清晰。再加上JS对数据类型的弱化,即使要表示字节数组,也只能通过普通数组的方式表示。

HTML5的建立对前端而言是颠覆性的,一方面基于XHR2, 使上传下载二进制内容成为可能;另一方面,WebGL/Canvas等新技术需要JS与显卡之间进行大量的、实时的数据交换,而其数据通信的形式必须是二进制。这样,JS操作二进制成为了必然。

在JS中,可以通过ArrayBuffer和类型化数组(Typed Array)在内存中对二进制数据进行操作。

ArrayBuffer

ArrayBuffer是一段连续的长度固定的字节序列,如:通过实例化ArrayBuffer对象在内存中创建一段二进制存储空间(或叫二进制缓冲区),

// 创建一段字节长度为8的内存空间
var buffer = new ArrayBuffer(8);
// 获取字节长度
console.log(buffer.byteLength); // 8

由于是连续的内存空间,故在其上进行的读写操作都会比普通JS Array快很多。

但需要说明的是:ArrayBuffer只是存储数据的区域,无法进行读写。若想进行访问,需要借助类型化数组(Typed Array)

故可以理解为:类型化数组是访问ArrayBuffer中数据的接口

类型化数组

类型化数组(或称视图view)是读写ArrayBuffer中数据的接口,JS可以通过8种不同的接口创建类型化数组,分别为:

名称 描述 字节长度
Int8Array 8位有符号整数 1
Uint8Array 8位无符号整数 1
Int16Array 16位有符号整数 2
Uint16Array 16位无符号整数 2
Int32Array 32位有符号整数 4
Uint32Array 32位无符号整数 4
Float32Array 32位浮点数 4
Float64Array 64位浮点数 8

通过类型化数组可以对ArrayBuffer中的数据进行读写,一段ArrayBuffer上可以重叠多个类型化数组。

// 创建一段12字节的ArrayBuffer
var b = new ArrayBuffer(12);
// 在b上创建一个视图v1,视图中每个元素类型为Uint8(占1字节),开始于字节索引0,结束于ArrayBuffer结尾
var v1 = new Uint8Array(b);
// 在b上创建一个视图v2,视图中每个元素类型为Uint32(占4字节),开始于字节索引4,结束于ArrayBuffer结尾
var v2 = new Uint32Array(b,4);
// 在b上创建一个视图v3,视图中每个元素类型为Uint16(占2字节),开始于字节索引2,视图长度为2,结束于字节索引5
var v3 = new Uint16Array(b,2,2);

下面画图说明存储方式:

[HTML5] ArrayBuffer与类型化数组

如图可见,一段ArrayBuffer上重叠了三个视图,可以通过三种方式访问ArrayBuffer中的数据

此时做如下测试:

1、通过v1向b中写入数据

2、通过v1、v2、v3从b中读取数据

[HTML5] ArrayBuffer与类型化数组

下面简单说明下各输出:

首先通过v1为每个元素赋值为十进制1,则ArrayBuffer中每个元素存储的二进制为00000001

通过v2读取,v2[0]和v2[1]中读取出的二进制均为00000001000000010000000100000001,转换为十进制即为16843009

通过v3读取,v3[0]和v3[1]中读取出的二进制均为0000000100000001,转换为十进制即为257

由此我们可以归纳出ArrayBuffer与类型化数组间的关系:

  • ArrayBuffer存储二进制数据,但只有通过类型化数组才能进行二进制数据的读写
  • 一段ArrayBuffer上可以重叠多个不同的类型化数组,不同类型化数组影响对ArrayBuffer中数据的读写方式

总结

本篇主要介绍如何对内存中的二进制内容进行读写,并重点介绍了ArrayBuffer及类型化数组的关系。写这篇的目的也是在于解释ArrayBuffer中二进制数据存在的形式,但往往我们操作本地文件时,并不需要关心二进制数据内容是如何排列的,故此处不讨论字节序或对齐等问题,以后有机会可能会结合Canvas进行说明。

参考资料

MDN_ArrayBuffer

MDN_TypedArray

[HTML5] ArrayBuffer与类型化数组的更多相关文章

  1. HTML5 ArrayBuffer:类型化数组 (二)

    类型化数组是JavaScript操作二进制数据的一个接口. 这要从WebGL项目的诞生说起,所谓WebGL,就是指浏览器与显卡之间的通信接口,为了满足JavaScript与显卡之间大量的.实时的数据交 ...

  2. ArrayBuffer:类型化数组

    类型化数组是JavaScript操作二进制数据的一个接口. 这要从WebGL项目的诞生说起,所谓WebGL,就是指浏览器与显卡之间的通信接口,为了满足JavaScript与显卡之间大量的.实时的数据交 ...

  3. 对类型化数组(Typed Array)与ArrayBuffer的理解 转囧囧

    类型化数组(Typed Array)也是HTML5中新引入的API.用一句话解释类型化数组就是:它是JS操作二进制数据的接口. 众所周知,直接操作二进制数据可以使程序更为高效, 尽管JS对常规数组做了 ...

  4. Javascript高级编程学习笔记(95)—— WebGL(1) 类型化数组

    WebGL webgl 是针对 canvas 的 3D上下文,与其它Web技术不同,WebGL并非是W3C制定的标准,而是由 Khronos Group 制定的. 类型化数组 WebGL所涉及的复杂运 ...

  5. ES6躬行记(13)——类型化数组

    类型化数组(Typed Array)是一种处理二进制数据的特殊数组,它可像C语言那样直接操纵字节,不过得先用ArrayBuffer对象创建数组缓冲区(Array Buffer),再映射到指定格式的视图 ...

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

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

  7. javascript ArrayBuffer类型化数组和视图的操作

    个人理解类型化数据就是内存分配区域,不同数据的存储就是视图DataView咯 var buffers = []; var json = {"id":100, "name& ...

  8. Scala编程入门---数组操作之Array.ArrayBuffer以及遍历数组

    在Scala中,Array代表的含义与Java类似,也是长度不可改变的数组.此外,由于Scala与java都是运行在JVM中,双方可以互相调用,因此Scala数组底层实际上是java数组.列如字符串数 ...

  9. Scala 数组操作之Array、ArrayBuffer以及遍历数组

    ArrayBuffer 在Scala中,如果需要类似于Java中的ArrayList这种长度可变的集合类,则可以使用ArrayBuffer. // 如果不想每次都使用全限定名,则可以预先导入Array ...

随机推荐

  1. 实时事件统计项目:优化flume:用file channel代替mem channel

    背景:利用kafka+flume+morphline+solr做实时统计. solr从12月23号开始一直没有数据.查看日志发现,因为有一个同事加了一条格式错误的埋点数据,导致大量error. 据推断 ...

  2. 题目1005:Graduate Admission

    题目1005:Graduate Admission 时间限制:1 秒 内存限制:32 兆 特殊判题:否 题目描述: It is said that in 2011, there are about 1 ...

  3. C++ Primer 学习笔记_62_重载操作符与转换 --调用操作符和函数对象

    重载操作符与转换 --调用操作符和函数对象 引言: 能够为类类型的对象重载函数调用操作符:一般为表示操作的类重载调用操作符! struct absInt { int operator() (int v ...

  4. 【转】linux建立软链接

    实例:ln -s /home/gamestat    /gamestat linux下的软链接类似于windows下的快捷方式 ln -s a b 中的 a 就是源文件,b是链接文件名,其作用是当进入 ...

  5. PHP常用表达式用法

    1.匹配正整数:/^[1-9]\d*$/ 2.匹配非负整数(正整数+0):/^\d+$/ 3.匹配中文:/^[\x{4e00}-\x{9fa5}]+$/u 4.匹配Email:/^\w+([-+.]\ ...

  6. JQUERY获取loaded 宽高这么变态

    JQUERY获取loaded 宽高这么变态: $('<img/>').attr('src',img.src).load(function() { img.Owidth = $(this). ...

  7. Perl文件句柄引用

    目前还没介绍Perl的面向对象,所以这节内容除了几个注意点,没什么可讲的. 以前经常使用大写字母的句柄方式(即所谓的裸字文件句柄,bareword filehandle),现在可以考虑转向使用变量文件 ...

  8. C&num;核心基础--静态类&amp&semi;部分类

    静态类 用 static 关键字修饰的类叫做静态类,静态类通常用来定义工具类.静态类不能实例化,不能从指定基类继承而来,静态类隐式从 Object 类继承而来.静态类只能包含静态成员和常量,因为常量是 ...

  9. File类 详解!

    package cn.zhoucufeng; import java.io.File; import java.io.IOException; import java.util.Arrays; imp ...

  10. 今天整理了一下Winform用的UI插件信息

    平时主要用了一下几个比较好的UI控件: 1:IrisSkin2 皮肤插件.这是一款与编程开发相关的素材资源,主要是提供一些采用IrisSkin2.dll控件进行软件窗口换肤的素材文件,包括一些GIF图 ...