180

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

4

13 回答 13

189

的实例Buffer也是Uint8Arraynode.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;
}
于 2012-08-23T22:41:43.017 回答
88

无依赖,最快,Node.js 4.x 及更高版本

Buffers 是Uint8Arrays,所以你只需要切片(复制)它的 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 Buffers(默认小于 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)。

于 2015-07-13T22:04:20.807 回答
80

“从 ArrayBuffer 到 Buffer”可以这样完成:

var buffer = Buffer.from( new Uint8Array(ab) );
于 2013-06-12T11:20:07.340 回答
34

一种更快的编写方法

var arrayBuffer = new Uint8Array(nodeBuffer).buffer;

但是,这似乎比建议的 toArrayBuffer 函数在具有 1024 个元素的缓冲区上运行慢了大约 4 倍。

于 2013-10-23T14:06:51.650 回答
21
于 2018-01-24T08:51:09.403 回答
11

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

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

buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)
于 2014-03-04T07:17:23.177 回答
2

您可以将 aArrayBuffer视为 typed Buffer

因此,AnArrayBuffer总是需要一个类型(所谓的“Array Buffer View”)。通常,Array Buffer View的类型为Uint8ArrayUint16Array

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!"
于 2017-08-30T16:31:12.447 回答
1

ABufferview一个ArrayBuffer。您可以ArrayBuffer使用该buffer属性进入内部包装。

这是共享内存,不需要复制。

const arrayBuffer = theBuffer.buffer

如果您想要一个数据,请从原始数据(不是从包装的 ArrayBuffer)copy创建另一个,然后引用其包装的.BufferBufferArrayBuffer

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
于 2022-02-15T12:01:10.673 回答
0

我为 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++;
}
于 2015-07-06T09:54:27.970 回答
0

现在有一个非常有用的 npm 包:buffer https ://github.com/feross/buffer

它尝试提供与节点的 Buffer API 100% 相同的 API,并允许:

还有更多。

于 2019-11-02T13:36:45.610 回答
0

这个 Proxy 会将缓冲区作为任何 TypedArrays 公开,没有任何副本。:

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

它仅适用于 LE,但可以轻松移植到 BE。此外,从来没有真正测试过它的效率。

于 2017-02-20T02:07:40.743 回答
-2

NodeJS,在某一时刻(我认为是 v0.6.x)支持 ArrayBuffer。我在这里创建了一个用于 base64 编码和解码的小型库,但是自从更新到 v0.7 后,测试(在 NodeJS 上)失败了。我正在考虑创建一些使其正常化的东西,但在此之前,我认为Buffer应该使用 Node 的本机。

于 2012-01-26T08:50:04.093 回答
-6

我已经将我的节点更新到版本 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 磁盘映像。

于 2015-11-09T09:57:17.767 回答