将二进制NodeJS缓冲区转换为JavaScript ArrayBuffer

如何将一个NodeJS二进制缓冲区转换为JavaScript ArrayBuffer?

Buffer的实例也是 node.js 4.x及更高版本中的Uint8Array实例 。 因此,最有效的解决scheme是直接访问buf.buffer属性,按照https://stackoverflow.com/a/31394257/1375574 。 如果你需要去另外一个方向,Buffer构造函数也需要一个ArrayBufferView参数。

请注意,这不会创build一个副本,这意味着写入任何ArrayBufferView将写入到原始的Buffer实例。


在较早的版本中,node.js将ArrayBuffer作为v8的一部分,但是Buffer类提供了更灵活的API。 为了读取或写入ArrayBuffer,您只需要创build一个视图并复制。

从缓冲区到ArrayBuffer:

 function toArrayBuffer(buf) { var ab = new ArrayBuffer(buf.length); var view = new Uint8Array(ab); for (var i = 0; i < buf.length; ++i) { view[i] = buf[i]; } return ab; } 

从ArrayBuffer到Buffer:

 function toBuffer(ab) { var buf = new Buffer(ab.byteLength); var view = new Uint8Array(ab); for (var i = 0; i < buf.length; ++i) { buf[i] = view[i]; } return buf; } 

“从ArrayBuffer到缓冲区”可以这样做:

 var buffer = new Buffer( new Uint8Array(ab) ); 

一个更快的方式来写它

 var arrayBuffer = new Uint8Array(nodeBuffer).buffer; 

但是,这似乎比在1024个元素的缓冲区上build议的toArrayBuffer函数慢大约4倍。

  • 没有依赖关系,最快的节点4.x和更高版本

缓冲区是Uint8Arrays,所以你只需要访问它的ArrayBuffer。 这是O(1)

  // node buffer var b = new Buffer(512); // ArrayBuffer var ab = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength); // TypedArray var ui32 = new Uint32Array(b.buffer, b.byteOffset, b.byteLength / Uint32Array.BYTES_PER_ELEMENT); 

slice和补偿的东西是必需的,因为小缓冲区(我认为是<4096字节)是共享ArrayBuffer上的视图。 没有它,你可能会得到一个包含来自另一个TypedArray的数据的ArrayBuffer。

  • 没有依赖关系,速度适中,任何版本的节点

用马丁·汤姆森的答案 ,在O(n)时间运行。 (另请参阅我对答案的答复,关于非优化的答案。使用DataView是慢的,即使您需要翻转字节,也有更快的方法来做到这一点。

  • 依赖,快速,任何版本的节点

您可以使用https://www.npmjs.com/package/memcpy在任一方向(Buffer to ArrayBuffer并返回)。 这比在这里发布的其他答案快,是一个写得很好的图书馆。 节点0.12到iojs 3.x要求使用ngossen的fork(请参阅这个 )。

使用以下优秀的npm包: to-arraybuffer

或者,你可以自己实现它。 如果您的缓冲区被称为buf ,请执行以下操作:

 buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) 

此代理将公开任何TypedArray的缓冲区,没有任何副本。 :

https://www.npmjs.com/package/node-buffer-as-typedarray

它只适用于LE,但可以轻松移植到BE。 另外,从来没有实际testing这是多高效。

您可以将ArrayBuffer视为一个types化的Buffer

因此ArrayBuffer总是需要一个types(即所谓的“Array Buffer View”)。 通常, arrays缓冲区视图具有Uint8ArrayUint16Arraytypes。

Renato Mangini有一篇关于在ArrayBuffer和String之间转换的好文章。

我已经总结了一个代码示例中的基本部分(对于Node.js)。 它还演示了如何在types化的ArrayBuffer和非types化的Buffer之间进行转换。

 function stringToArrayBuffer(string) { const arrayBuffer = new ArrayBuffer(string.length); const arrayBufferView = new Uint8Array(arrayBuffer); for (let i = 0; i < string.length; i++) { arrayBufferView[i] = string.charCodeAt(i); } return arrayBuffer; } function arrayBufferToString(buffer) { return String.fromCharCode.apply(null, new Uint8Array(buffer)); } const helloWorld = stringToArrayBuffer('Hello, World!'); // "ArrayBuffer" (Uint8Array) const encodedString = new Buffer(helloWorld).toString('base64'); // "string" const decodedBuffer = Buffer.from(encodedString, 'base64'); // "Buffer" const decodedArrayBuffer = new Uint8Array(decodedBuffer).buffer; // "ArrayBuffer" (Uint8Array) console.log(arrayBufferToString(decodedArrayBuffer)); // prints "Hello, World!" 

我尝试了上面的Float64Array,它只是没有工作。

我最终意识到数据需要被正确的读入“INTO”视图。 这意味着从源缓冲区一次读取8个字节。

无论如何,这是我最终与…

 var buff = new Buffer("40100000000000004014000000000000", "hex"); var ab = new ArrayBuffer(buff.length); var view = new Float64Array(ab); var viewIndex = 0; for (var bufferIndex=0;bufferIndex<buff.length;bufferIndex=bufferIndex+8) { view[viewIndex] = buff.readDoubleLE(bufferIndex); viewIndex++; } 

NodeJS,在一点(我认为它是v0.6.x)有ArrayBuffer的支持。 我在这里创build了一个用于base64编码和解码的小型库,但是由于更新到v0.7,所以testing(在NodeJS上)失败。 我正在考虑创build一个正常化的东西,但直到那时,我才会使用Node的本地Buffer

我已经更新我的节点到版本5.0.0我工作与此:

 function toArrayBuffer(buffer){ var array = []; var json = buffer.toJSON(); var list = json.data for(var key in list){ array.push(fixcode(list[key].toString(16))) } function fixcode(key){ if(key.length==1){ return '0'+key.toUpperCase() }else{ return key.toUpperCase() } } return array } 

我用它来检查我的vhd磁盘映像。