我正在通过XHR加载远程资产,并将其作为arrayBuffers接收。基础数据取决于float32。我需要对这些数组缓冲区进行一些进一步的操作,例如连接和合并。对于这些操作,我正在尝试buffer module

我发现使用Buffer模块和底层Uint8Array更改了预期的float32输出

TypedArray构造函数实例化new Float32Array时,数据正确。

new Float32Array(action.payload.arrayBuffer)
Float32Array(9072) [-5, 35, -5, 255, 127, 128, 128, 1, 0.2666666805744171, 0.2666666805744171, 0.2666666805744171, 1, -5, 34, -5, 255, 127, 128, 128, 1, 0.2666666805744171, 0.2666666805744171, 0.2666666805744171, 1, -5, 35, -2, 255, 127, 128, 128, 1, 0.2666666805744171, 0.2666666805744171, 0.2666666805744171, 1, -5, 34, -2, 255, 127, 128, 128, 1, 0.2666666805744171, 0.2666666805744171, 0.2666666805744171, 1, -5, 35, -2, 255, 127, 128, 128, 1, 0.2666666805744171, 0.2666666805744171, 0.2666666805744171, 1, -5, 34, -5, 255, 127, 128, 128, 1, 0.2666666805744171, 0.2666666805744171, 0.2666666805744171, 1, -5, 38, -2, 255, 127, 128, 128, 2, 0.9411764740943909, 0.3686274588108063, 0.10980392247438431, 1, -5, 34, -2, 255, 127, 128, 128, 2, 0.9411764740943909, 0.3686274588108063, 0.10980392247438431, 1, -5, 38, 1, 255, …]


TypedArray方法初始化from时,数据为空。这是可以预期的,因为from方法需要一个可迭代的数组,而arrayBuffer则不是。

Float32Array.from(action.payload.arrayBuffer)
Float32Array []


从使用基础Uint8ArrayBufferUint8Array转换时,浮点数据将发生突变。

Float32Array.from(new Uint8Array(action.payload.arrayBuffer))
Float32Array(36288) [0, 0, 160, 192, 0, 0, 12, 66, 0, 0, 160, 192, 0, 0, 127, 67, 0, 0, 254, 66, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 128, 63, 137, 136, 136, 62, 137, 136, 136, 62, 137, 136, 136, 62, 0, 0, 128, 63, 0, 0, 160, 192, 0, 0, 8, 66, 0, 0, 160, 192, 0, 0, 127, 67, 0, 0, 254, 66, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 128, 63, 137, 136, 136, 62, 137, 136, 136, 62, 137, 136, 136, 62, 0, 0, 128, 63, 0, 0, 160, 192, …]

Float32Array.from(Buffer.from(action.payload.arrayBuffer))
    Float32Array(36288) [0, 0, 160, 192, 0, 0, 12, 66, 0, 0, 160, 192, 0, 0, 127, 67, 0, 0, 254, 66, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 128, 63, 137, 136, 136, 62, 137, 136, 136, 62, 137, 136, 136, 62, 0, 0, 128, 63, 0, 0, 160, 192, 0, 0, 8, 66, 0, 0, 160, 192, 0, 0, 127, 67, 0, 0, 254, 66, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 128, 63, 137, 136, 136, 62, 137, 136, 136, 62, 137, 136, 136, 62, 0, 0, 128, 63, 0, 0, 160, 192, …]


最终输出的这种差异完全打破了我期望new Float32Array输出的工作流水线

我正在寻找有关这种情况发生的原因的解释和教育反馈。

最佳答案

这是因为Uint8数组(视图)保存的每个单个值都根据视图而不是基础ArrayBuffer强制转换为完整的Float32值。

如果您有一个Uint8Array视图,该视图包含例如4个条目:

Uint8 -> [1,2,3,4]


在ArrayBuffer中,它将看起来像这样(ArrayBuffer始终是字节数组):

0x01020304


然后发生的事情是,当您将Uint8视图转换为Float32视图时,将使用视图表示形式中的值(即[1,2,3,4]),而不是底层的ArrayBuffer,因此这些条目仅被转换为新的条目但是以不同的类型仍然代表与原始视图相同的数字[1,2,3,4]:

Float32 -> [1,2,3,4]   (each entry stored as 32-bit value)


新的ArrayBuffer看起来像(手动转换,但您会明白的)由Float32表示的4个字节(32位)x 4个值组成-还请注意,浮点值使用4以IEEE754格式编码Float32类型表示的每个数字的字节:

0x00003F80 00000040 00004040 00004080 (=1,2,3,4 as IEEE754 encoded floating point values)


您还可以从新的基础ArrayBuffer的字节大小(从问题中的数字)中看到以下内容:

9,072 x 4 = 36,288 bytes


为了获得结果,您期望必须直接通过其buffer属性使用缓冲区:

new Float32Array(uint8array.buffer);  // notice .buffer -> actual ArrayBuffer


这与您在问题的第一行中所做的相同:

new Float32Array(action.payload.arrayBuffer);


字节顺序是这里的一个方面,但是由于直接从XHR和Float32视图使用您的数字是正确的,因此在这种情况下这可能不是问题。

简而言之:不会发生突变,但是不同的类型(通过视图)需要不同数量的字节,在这种情况下,Uint8来自底层ArrayBuffer的单个字节,而Float32来自同一Array的4个字节,这意味着它们将转换为从视图中可以看到不同的值。

关于javascript - Buffer和TypedArray转换会导致数据突变?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47746378/

10-13 00:15