Como converter um buffer binário do NodeJS em um JavaScript ArrayBuffer?
javascript
node.js
binary
buffer
arraybuffer
Drake Amara
fonte
fonte
Array
. Portanto, para armazenar muitos carros alegóricos, é necessárioFloat32Array
onde são necessários 4 bytes. E se você deseja serializar rapidamente esses flutuadores em um arquivo, precisará de umBuffer
, pois a serialização para JSON leva séculos.Respostas:
Instâncias de
Buffer
também são instânciasUint8Array
no node.js 4.xe superior. Portanto, a solução mais eficiente é acessar abuf.buffer
propriedade diretamente, conforme https://stackoverflow.com/a/31394257/1375574 . O construtor Buffer também aceita um argumento ArrayBufferView se você precisar ir na outra direção.Observe que isso não criará uma cópia, o que significa que as gravações em qualquer ArrayBufferView serão gravadas na instância original do Buffer.
Nas versões anteriores, o node.js possui o ArrayBuffer como parte da v8, mas a classe Buffer fornece uma API mais flexível. Para ler ou gravar em um ArrayBuffer, você só precisa criar uma exibição e copiar.
Do buffer para o ArrayBuffer:
De ArrayBuffer para Buffer:
fonte
size&0xfffffffe
, copie números inteiros de 32 bits; se houver 1 byte restante, copie o número inteiro de 8 bits; se 2 bytes, copie o número inteiro de 16 bits; e, se 3 bytes, copie o número inteiro de 16 e 8 bits.ab
devolvido? Não há nada feitoab
? Eu sempre recebo{}
como resultado.slice()
método retorna um novoArrayBuffer
cujo conteúdo é uma cópia dosArrayBuffer
bytes deste, desde o início, inclusive, até o fim, exclusivo.' - MDNArrayBuffer.prototype.slice()
Sem dependências, mais rápido, Node.js 4.xe posterior
Buffer
s sãoUint8Array
s, então você só precisa cortar (copiar) sua região do suporteArrayBuffer
.O
slice
material e offset são necessários porqueBuffer
s pequenos (menos de 4 kB por padrão, metade do tamanho do pool ) podem ser vistas em um compartilhamentoArrayBuffer
. Sem fatiar, você pode acabar com umArrayBuffer
dado contendo outroBuffer
. Veja a explicação nos documentos .Se você precisar de um
TypedArray
, poderá criar um sem copiar os dados:Sem dependências, velocidade moderada, qualquer versão do Node.js
Use a resposta de Martin Thomson , que é executada em O (n) tempo. (Veja também minhas respostas aos comentários sobre a resposta dele sobre não otimizações. O uso de um DataView é lento. Mesmo se você precisar inverter bytes, existem maneiras mais rápidas de fazer isso.)
Dependência, rápida, Node.js ≤ 0.12 ou iojs 3.x
Você pode usar https://www.npmjs.com/package/memcpy para ir em qualquer direção (Buffer para ArrayBuffer e vice-versa). É mais rápido que as outras respostas postadas aqui e é uma biblioteca bem escrita. O nó 0.12 a iojs 3.x requer o fork do ngossen (consulte isso ).
fonte
.byteLength
e.byteOffset
documentados?var ab = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
salvou meu dia"De ArrayBuffer para Buffer" pode ser feito desta maneira:
fonte
Uma maneira mais rápida de escrever
No entanto, isso parece ser executado aproximadamente quatro vezes mais lento que a função toArrayBuffer sugerida em um buffer com 1024 elementos.
fonte
Buffer
também são instâncias doUint8Array
Node.js. 4.xe superior. Para versões inferiores do Node.js., você precisa implementar umatoArrayBuffer
função.1. A
Buffer
é apenas uma visão para analisar umArrayBuffer
.A
Ode Node.js 9.4.0Buffer
, de fato, é aFastBuffer
, queextends
(herda de)Uint8Array
, que é uma visão da unidade de octetos ("acessador parcial") da memória real, anArrayBuffer
./lib/buffer.js#L65-L73
2. O tamanho de um
ArrayBuffer
e o tamanho de sua visualização podem variar.Razão # 1:
Buffer.from(arrayBuffer[, byteOffset[, length]])
.Com
Buffer.from(arrayBuffer[, byteOffset[, length]])
, você pode criar umBuffer
com especificando sua posição subjacenteArrayBuffer
e a posição e tamanho da exibição.Razão # 2:
FastBuffer
alocação de memória.Ele aloca a memória de duas maneiras diferentes, dependendo do tamanho.
ArrayBuffer
que se encaixa exatamente na memória necessária./lib/buffer.js#L306-L320
Ode Node.js 9.4.0/lib/buffer.js#L98-L100
O que você quer dizer com " pool de memória "?
Um conjunto de memórias é um bloco de memória pré-alocado de tamanho fixo para manter pequenos blocos de memória por
Buffer
s. O uso mantém os blocos de memória de tamanho pequeno firmemente juntos, evitando a fragmentação causada pelo gerenciamento separado (alocação e desalocação) de blocos de memória de tamanho pequeno.Neste caso, os pools de memória são
ArrayBuffer
s cujo tamanho é de 8 KiB por padrão, que é especificado emBuffer.poolSize
. Quando é para fornecer um pedaço de memória de tamanho pequeno para aBuffer
, ele verifica se o último pool de memória possui memória disponível suficiente para lidar com isso; nesse caso, cria umBuffer
que "visualiza" o pedaço parcial fornecido do conjunto de memórias; caso contrário, cria um novo conjunto de memórias e assim por diante.Você pode acessar o subjacente
ArrayBuffer
de aBuffer
. OBuffer
'sbuffer
propriedade (ou seja, herdadaUint8Array
) prende-lo. Um “pequeno”Buffer
dabuffer
propriedade é umArrayBuffer
que representa todo o pool de memória. Portanto, neste caso, oArrayBuffer
eBuffer
varia em tamanho.3. Portanto, precisamos extrair a memória que " visualiza ".
Como o
ArrayBuffer
tamanho é fixo, precisamos extraí-lo fazendo uma cópia da peça. Para fazer isso, usamosBuffer
'sbyteOffset
propriedade elength
propriedade , que são herdadasUint8Array
, e oArrayBuffer.prototype.slice
método , que faz uma cópia de uma parte de umArrayBuffer
. Oslice()
método -ing aqui foi inspirado no @ZachB .4. Melhoria de desempenho
Se você usar os resultados como somente leitura, ou se estiver modificando o
Buffer
conteúdo da entrada , poderá evitar cópias desnecessárias da memória.fonte
obtain_arraybuffer
:buf.buffer.subarray
parece não existir. Você quis dizerbuf.buffer.slice
aqui?ArrayBuffer.prototype.slice
e depois modifiquei paraUint8Array.prototype.subarray
. Ah, e eu fiz errado. Provavelmente ficou um pouco confuso naquela época. Está tudo bem agora, graças a você.Use o seguinte pacote de npm excelente:
to-arraybuffer
.Ou, você pode implementá-lo você mesmo. Se seu buffer for chamado
buf
, faça o seguinte:fonte
Você pode pensar em um
ArrayBuffer
como digitadoBuffer
.Um,
ArrayBuffer
portanto, sempre precisa de um tipo (a chamada "Visualização de buffer de matriz"). Normalmente, a exibição de buffer de matriz tem um tipo deUint8Array
ouUint16Array
.Há um bom artigo de Renato Mangini sobre a conversão entre um ArrayBuffer e um String .
Resumi as partes essenciais em um exemplo de código (para Node.js). Também mostra como converter entre o digitado
ArrayBuffer
e o não digitadoBuffer
.fonte
Eu tentei o acima para um Float64Array e ele simplesmente não funcionou.
Acabei percebendo que realmente os dados precisavam ser lidos 'NA' visualização em partes corretas. Isso significa ler 8 bytes de cada vez no buffer de origem.
Enfim, é isso que eu acabei com ...
fonte
Buffer.read*
métodos também são lentos.Este proxy irá expor o buffer como qualquer um dos TypedArrays, sem nenhuma cópia. :
https://www.npmjs.com/package/node-buffer-as-typedarray
Funciona apenas no LE, mas pode ser facilmente portado para o BE. Além disso, nunca chegou a testar o quão eficiente isso é.
fonte
Agora há um pacote npm muito útil para isso:
buffer
https://github.com/feross/bufferEle tenta fornecer uma API 100% idêntica à API de buffer do nó e permite:
e mais alguns.
fonte
O NodeJS, em um ponto (acho que era v0.6.x), tinha suporte ao ArrayBuffer. Criei uma pequena biblioteca para codificação e decodificação base64 aqui , mas desde a atualização para a v0.7, os testes (no NodeJS) falham. Estou pensando em criar algo que normalize isso, mas até então, acho que o nativo do Node
Buffer
deve ser usado.fonte
Já atualizei meu nó para a versão 5.0.0 e trabalho com isso:
Eu o uso para verificar minha imagem de disco vhd.
fonte
toArrayBuffer(new Buffer([1,2,3]))
->['01', '02', '03']
- isso está retornando uma matriz de seqüências de caracteres, não números inteiros / bytes.