从存储为节点缓冲区的字节数组创建类型化数组

时间:2015-06-02 19:20:15

标签: node.js

从节点docs关于从Buffers:

创建类型化数组
  

缓冲区的内存被解释为数组,而不是字节数组。那   是,new Uint32Array(new Buffer([1,2,3,4]))创建一个4元素   元素Uint32Array的{​​{1}},而不是[1,2,3,4]   元素Uint32Array[0x1020304]

这与普通的javascript形成对比,其中从ArrayBuffer创建类型化数组视图使用ArrayBuffer的内存作为字节(如C ++中的[0x4030201])。在节点缓冲区上运行时,我在节点中需要这种行为。

我可以将Buffer转换为ArrayBuffer,但这对我的应用来说太慢了。 (我尝试了很多方法 - 但它们都是O(n)时间。)(编辑:我发现的最快的方法是this,这是一个单一的memmove op并且相当快,但仍然在释放对原始缓冲区的引用之前,至少会有2倍的内存消耗。)

是否有任何(快速/ O(1))方式从缓冲区获取类型化数组,使用缓冲区的内容作为字节而不是元素?(所需的类型化数据元素大小是> ; 1个字节,不用说了。)

2 个答案:

答案 0 :(得分:3)

据我所知,如果不在内存中复制数据,就无法做到这一点。 即使您的示例new Uint32Array(new Buffer([1,2,3,4]))在内部也这样做(意味着它不是O(1))。

请注意,键入的数组只是ArrayBuffer视图(不是Buffer,这是不可能的)。 new Uint32Array(array)创建ArrayBuffer4 * array.length个字节。您可以使用uint32Array.buffer访问它。构造函数会将您的Buffer与普通Array区别开来。

我所知道的最佳解决方案是the one you already found

使用Uint32Array进行尝试的另一个问题是它depends on platform byte order。如果您想要安全,可以迭代Buffer DataView或使用findById

答案 1 :(得分:2)

从节点4.0开始,Buffers是Uint8Arrays,可以直接在它们上构建新视图:

var b = new Buffer([1,2,3,4]);
new Uint32Array(b.buffer, b.byteOffset);

这个迷你示例假设b大于~4096(缓冲区拥有自己的内存块与共享更大块的阈值)。有关详细信息,请参阅Convert a binary NodeJS Buffer to JavaScript ArrayBuffer - 通常您应致电b.slice()以仅对您拥有的内存进行操作。