【问题标题】:Javascript combine ArrayBuffer partsJavascript 结合 ArrayBuffer 部分
【发布时间】:2017-01-22 23:08:35
【问题描述】:

我需要将 2 个现有 arrayBuffers 的 2 个部分组合成一个新的。

我正在构建一个解析器,数据来自随机大小的数组缓冲区,数据将溢出到一个的末尾,进入另一个的开头。所以我需要创建一个新的输出缓冲区并复制一个缓冲区末尾的一部分和另一个缓冲区开头的一部分。输出将只是一个 Arraybuffer。

从这个演示开始,我打算用一些偏移量制作 Uint8Arrays,然后使用 set,问题是某些组合抛出 Invalid typed array length。我不会事先知道每个数组的长度或偏移量。

var buffer1 = new ArrayBuffer(8);
var buffer2 = new ArrayBuffer(8);
var buffer3 = new ArrayBuffer(8);

var uint8_1 = new Uint8Array(buffer1);
var uint8_2 = new Uint8Array(buffer2);
var uint8_3 = new Uint8Array(buffer3);

uint8_1.fill(1);
uint8_2.fill(2);

var uint8_1_slice = new Uint8Array(buffer1 , 0 , 3);
var uint8_2_slice = new Uint8Array(buffer2 , 4, 7);

对于这个演示,需要将 buffer3 设置为 1,1,1,1,2,2,2,2。

不能使用切片

【问题讨论】:

    标签: javascript typed-arrays typedarray uint8array


    【解决方案1】:

    我看到有些人只使用array.length。只要数组每个元素只有 1 个字节就可以了。如果其他类型的数组被填满也很好,但在这个例子中 a2 不是。这就是为什么最好使用byteLength 这也是 Blob 构造函数连接各部分的方式。

    // Concatenate a mix of typed arrays
    function concatenate(...arrays) {
      // Calculate byteSize from all arrays
      let size = arrays.reduce((a,b) => a + b.byteLength, 0)
      // Allcolate a new buffer
      let result = new Uint8Array(size)
    
      // Build the new array
      let offset = 0
      for (let arr of arrays) {
        result.set(arr, offset)
        offset += arr.byteLength
      }
    
      return result
    }
    
    // the total length of 1-3 = 5
    // the total byteLength of 1-3 = 6
    let a1 = Uint8Array.of(1, 2) // [1, 2]
    let a2 = Uint16Array.of(3) // [3] just for the fun of it 16 takes up 2 bytes
    let a3 = Uint8Array.of(4, 5) // [4, 5]
    
    concatenate(a1, a2, a3) // [1, 2, 3, 0, 4, 5]
    
    /********/
    var blob = new Blob([a1, a2, a3])
    var res = new Response(blob)
    res.arrayBuffer().then(buffer => console.log(new Uint8Array(buffer)))
    // [1, 2, 3, 0, 4, 5]
    

    【讨论】:

      【解决方案2】:

      对于这个演示,需要将 buffer3 设置为 1,1,1,1,2,2,2,2。

      您可以使用for 循环,如果变量n 小于uint8_1.byteLength / 2,则将uint8_3 设置为uint8_1 值,否则将uint8_3 设置为uint8_2 的值。

      var len = 8;
      
      var buffer1 = new ArrayBuffer(len);
      var buffer2 = new ArrayBuffer(len);
      var buffer3 = new ArrayBuffer(len);
      
      var uint8_1 = new Uint8Array(buffer1);
      var uint8_2 = new Uint8Array(buffer2);
      var uint8_3 = new Uint8Array(buffer3);
      
      uint8_1.fill(1);
      uint8_2.fill(2);
      // `len` : uint8_1.byteLength / 2 + uint8_2.byteLength / 2
      for (var n = 0; n < len; n++) {
        uint8_3[n] = n < len / 2 ? uint8_1[n] : uint8_2[n];
      }
      
      console.log(uint8_3);

      【讨论】:

      • 这是在正确的轨道上,但它应该使用 set,因为如果不是你一次复制 1 个字节。
      • 其实很抱歉,不能使用 slice,它会返回一个新数组。
      • @brianxautumn “实在抱歉,不能使用 slice,它会返回一个新数组” 不明白你的意思?是否要求不创建新数组?
      • 是的,在这种情况下,速度和内存使用非常非常重要。
      • 更好,但问题是它一次复制 1 个字节,而一次最多可以复制 8 个。
      猜你喜欢
      • 2012-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-18
      • 1970-01-01
      • 2018-04-29
      • 1970-01-01
      • 2015-05-01
      相关资源
      最近更新 更多