JavaScript 如何操作二进制数据

877 阅读3分钟

前言

最近在开发游戏相关的业务产品,控制游戏中的人物,需要频繁地发出操作指令,这些与服务器交互的数据是以二进制的形式。我们知道ES6提供了ArrayBuffer对象,相信大部分同学在实际开发中很少会用到,那么一起来看看在实际开发场景中是如何应用的吧。

ArrayBuffer

ArrayBuffer对象代表储存二进制数据的一段内存,它不能直接读写,只能通过视图(TypedArray视图和DataView视图)来读写,视图的作用是以指定格式解读二进制数据。

我们可以用此对象申请一块二进制数据缓冲区,举个栗子:申请一个长度为19个字节的内存空间

const buffer = new ArrayBuffer(19);

TypedArray 视图

ArrayBuffer对象作为内存区域,可以存放多种类型的数据。

目前,TypedArray视图一共包括 9 种类型,每一种视图都是一种构造函数。

  • Int8Array:8 位有符号整数,长度 1 个字节。

  • Uint8Array:8 位无符号整数,长度 1 个字节。

  • Uint8ClampedArray:8 位无符号整数数组,长度 1 个字节,溢出处理不同。

  • Int16Array:16 位有符号整数数组,长度 2 个字节。

  • Uint16Array:16 位无符号整数数组,长度 2 个字节。

  • Int32Array:32 位有符号整数数组,长度 4 个字节。

  • Uint32Array:32 位无符号整数数组,长度 4 个字节。

  • Float32Array:32 位浮点数数组,长度 4 个字节。

  • Float64Array:64 位浮点数数组,长度 8 个字节

详细介绍传送门 developer.mozilla.org/en-US/docs/…

常用的方法:

  • Uint8Array.prototype.set()

将多个值存储在类型化数组中。

  • Uint8Array.prototype.slice()

提取数组的一部分并返回一个新数组.

实践

export function StringtoBinary(str) {
    const len = getStrLeng(str);//获取字符串所占的字节数 (伪代码)
    const buffer = new ArrayBuffer(len + 8);//申明二进制缓冲区
    const view = new DataView(buffer);
    let utfData = encodeUtf8(str);//Utf8编码 (伪代码)
    utfData.forEach((item, index) => {
        if (index < 492) {
            utfData[index] = "0x" + item.toString(16);
        }
    });
    view.setInt16(0, len + 8, false);
    view.setInt8(2, 13);
    view.setInt32(4, len, false);
    //关键代码
    let strArray = new Int8Array(buffer);//申明一个接受ArrayBuffer作为参数的8位有符号整数数组
    strArray.set(utfData, 8);//在偏移量为8个字节的位置设置存储值
    return view;
};

DataView

DataView用于以二进制形式读取和写入多种数字类型ArrayBuffer,而不必关心平台的字节序。

DataView 视图提供 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 位浮点数。

实践

    export function ProtocolBlobKeyboard() {
    const buffer = new ArrayBuffer(19);//申明长度为19字节二进制缓冲区
    const view = new DataView(buffer);//接受ArrayBuffer作为参数,生成一个DataView视图
    view.setInt16(0, 19,false);//将一个有符号的16位整数值存储在从开头开始的指定字节偏移处 false:大端字节序 true:小端字节序
    
    view.setInt8(2, 4);//将带符号的8位整数(字节)值存储在距开头2字节偏移处
    ......
    return view;
    }

江湖再见

以上就是最近工作中,对于二进制数据如何进行读写操作,如果二进制字节长度较长,可以分组处理。

如果对你有些许帮助,还希望你能慷慨地点个赞,谢谢~