如何将 NodeJS 二进制缓冲区转换为 JavaScript ArrayBuffer?
13 回答
的实例Buffer
也是Uint8Array
node.js 4.x 及更高版本中的实例。因此,最有效的解决方案是根据https://stackoverflow.com/a/31394257/1375574buf.buffer
直接访问该属性。Buffer 构造函数还需要一个 ArrayBufferView 参数,如果你需要去另一个方向。
请注意,这不会创建副本,这意味着对任何 ArrayBufferView 的写入都将写入原始 Buffer 实例。
在旧版本中,node.js 将 ArrayBuffer 作为 v8 的一部分,但 Buffer 类提供了更灵活的 API。为了读取或写入 ArrayBuffer,您只需要创建一个视图并复制。
从缓冲区到 ArrayBuffer:
function toArrayBuffer(buf) {
const ab = new ArrayBuffer(buf.length);
const view = new Uint8Array(ab);
for (let i = 0; i < buf.length; ++i) {
view[i] = buf[i];
}
return ab;
}
从 ArrayBuffer 到缓冲区:
function toBuffer(ab) {
const buf = Buffer.alloc(ab.byteLength);
const view = new Uint8Array(ab);
for (let i = 0; i < buf.length; ++i) {
buf[i] = view[i];
}
return buf;
}
无依赖,最快,Node.js 4.x 及更高版本
Buffer
s 是Uint8Array
s,所以你只需要切片(复制)它的 backing 区域ArrayBuffer
。
// Original Buffer
let b = Buffer.alloc(512);
// Slice (copy) its segment of the underlying ArrayBuffer
let ab = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
slice
和偏移量是必需的,因为 small Buffer
s(默认小于 4 kB,池大小的一半)可以是 shared 上的视图ArrayBuffer
。如果不进行切片,您最终可能会得到ArrayBuffer
来自另一个的包含数据Buffer
。请参阅文档中的说明。
如果您最终需要一个TypedArray
,您可以在不复制数据的情况下创建一个:
// Create a new view of the ArrayBuffer without copying
let ui32 = new Uint32Array(b.buffer, b.byteOffset, b.byteLength / Uint32Array.BYTES_PER_ELEMENT);
无依赖,速度适中,任何版本的 Node.js
使用Martin Thomson 的答案,它在O(n)时间内运行。(另请参阅我对他关于非优化的回答的评论的回复。使用 DataView 很慢。即使您需要翻转字节,也有更快的方法来做到这一点。)
依赖,快速,Node.js ≤ 0.12 或 iojs 3.x
您可以使用https://www.npmjs.com/package/memcpy向任一方向前进(缓冲区到 ArrayBuffer 并返回)。它比此处发布的其他答案更快,并且是一个编写良好的库。节点 0.12 到 iojs 3.x 需要 ngossen 的 fork(请参阅this)。
“从 ArrayBuffer 到 Buffer”可以这样完成:
var buffer = Buffer.from( new Uint8Array(ab) );
一种更快的编写方法
var arrayBuffer = new Uint8Array(nodeBuffer).buffer;
但是,这似乎比建议的 toArrayBuffer 函数在具有 1024 个元素的缓冲区上运行慢了大约 4 倍。
使用以下优秀的 npm 包:to-arraybuffer
.
或者,您可以自己实现它。如果您的缓冲区被调用buf
,请执行以下操作:
buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)
您可以将 aArrayBuffer
视为 typed Buffer
。
因此,AnArrayBuffer
总是需要一个类型(所谓的“Array Buffer View”)。通常,Array Buffer View的类型为Uint8Array
或Uint16Array
。
Renato Mangini 有一篇关于在 ArrayBuffer 和 String 之间转换的好文章。
我已经在一个代码示例(针对 Node.js)中总结了基本部分。它还展示了如何在 typedArrayBuffer
和 untyped之间进行转换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!"
ABuffer
是view
一个ArrayBuffer
。您可以ArrayBuffer
使用该buffer
属性进入内部包装。
这是共享内存,不需要复制。
const arrayBuffer = theBuffer.buffer
如果您想要一个数据,请从原始数据(不是从包装的 ArrayBuffer)copy
创建另一个,然后引用其包装的.Buffer
Buffer
ArrayBuffer
const newArrayBuffer = Buffer.from(theBuffer).buffer
作为参考,从另一个方向,从一个ArrayBuffer
到一个Buffer
const arrayBuffer = getArrayBuffer()
const sharedBuffer = Buffer.from(arrayBuffer)
const copiedBuffer = Buffer.from(sharedBuffer)
const copiedArrayBuffer = copiedBuffer.buffer
我为 Float64Array 尝试了上述方法,但它不起作用。
我最终意识到确实需要以正确的块将数据“读取”到视图中。这意味着一次从源缓冲区读取 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++;
}
现在有一个非常有用的 npm 包:buffer
https ://github.com/feross/buffer
它尝试提供与节点的 Buffer API 100% 相同的 API,并允许:
- 将类型化数组转换为缓冲区:https ://github.com/feross/buffer#convert-typed-array-to-buffer
- 将缓冲区转换为类型化数组:https ://github.com/feross/buffer#convert-buffer-to-typed-array
还有更多。
这个 Proxy 会将缓冲区作为任何 TypedArrays 公开,没有任何副本。:
https://www.npmjs.com/package/node-buffer-as-typedarray
它仅适用于 LE,但可以轻松移植到 BE。此外,从来没有真正测试过它的效率。
NodeJS,在某一时刻(我认为是 v0.6.x)支持 ArrayBuffer。我在这里创建了一个用于 base64 编码和解码的小型库,但是自从更新到 v0.7 后,测试(在 NodeJS 上)失败了。我正在考虑创建一些使其正常化的东西,但在此之前,我认为Buffer
应该使用 Node 的本机。
我已经将我的节点更新到版本 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 磁盘映像。