将二进制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缓冲区视图具有Uint8Array
或Uint16Array
types。
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磁盘映像。