提取具有不同数据类型的缓冲区 示例

问题描述

缓冲区可以同时具有字符串和图像吗?如果是这样,如何分别提取它们。

一个示例案例是带有图像数据以及文件名数据的缓冲区。

解决方法

我以前使用过sharedArrayBuffers / arrayBuffers。

如果要存储图像像素数据,它将是一个u32-int数组,具有4个分别控制rbga的8位段...是的:您可以以'标头”,如果您对其进行编码并将其解码为int值...但是我很难理解为什么这可能是理想的。因为处理仅包含像素数据的原始像素数据更为简单。 (我通常将其保留为对象的属性,以及我想存储的所有其他数据)

,

数据缓冲区

类型化数组

您可以使用ArrayBuffer创建一个缓冲区来保存数据。然后,您使用typed array创建视图。例如,无符号字符Uint8Array。类型可以是8-16-32-64位(无符号整数),浮点数-双精度(32-64位浮点数)

一个缓冲区可以有很多视图。您可以像读取任何JS数组一样进行读写以查看。写入缓冲区时,这些值会自动转换为正确的类型,而从视图中读取时,这些值会转换为Number

示例

使用缓冲区和视图读取不同的数据类型

例如,假设您的文件数据具有4个字符的标头,然后是16位无符号整数块长度,然后是2个有符号16位整数坐标,以及更多数据

const fileBuffer = ArrayBuffer(fileSizeInBytes);

// Create a view of the buffer so we can fill it with file data
const dataRaw = new Uint8Array(data);
// load the data into dataRaw 

// To get a string from the data we can create a util function
function readBufferString(buffer,start,length) {

    // create a view at the position of the string in the buffer
    const bytes = new Uint8Array(buffer,length);

    // read each byte converting to JS unicode string
    var str = "",idx = 0;
    while (idx < length) { str += String.fromCharCode(bytes[idx++]) }
    return str;
}

// get 4 char chunk header at start of buffer    
const header = readBufferString(fileBuffer,4);
if (header === "HEAD") {
    // Create views for 16 bit signed and unsigned integers
    const ints = new Int16Array(fileBuffer);
    const uints = new Uint16Array(fileBuffer);
    const length = uints[2]; // get the length as unsigned int16
    const x = ints[3]; // get the x coord as signed int16
    const y = ints[4]; // get the y coord as signed int16

A DataView

以上示例是从单个缓冲区提取不同类型数据的一种方法。但是,较早的文件和某些数据源可能存在与创建多字节类型(例如32个整数)的字节顺序有关的问题。这称为endianness

要帮助使用正确的字节序并简化对缓冲区中所有不同数据类型的访问,可以使用DataView

数据视图使您可以按类型和字节序从缓冲区读取。例如,从缓冲区读取无符号的64位整数

 // fileBuffer is a array buffer with the data
 // Create a view
 const dataView = new DataView(fileBuffer);
 
 // read the 64 bit uint starting at the first byte in the buffer
 // Note the returned value is a BigInt not a Number
 const bInt = dataView.getBigUint64(0);

 // If the int was in little endian order you would use
 const bInt = dataView.getBigUint64(0,true); // true for little E
 

注释

  • 缓冲区不是动态的。这意味着它们不能增长和收缩,并且您必须知道创建缓冲区时需要多大的缓冲区。

  • 缓冲区往往比JavaScript的标准数组慢一点,因为在读取或写入缓冲区时存在很多类型强制性

  • 缓冲区可以跨线程传输(零复制传输),使其成为在WebWorkers之间分配大型数据结构的理想选择。还有一个SharedArrayBuffer,可让您在JS中创建真正的并行处理解决方案