Comment puis-je convertir un tampon binaire NodeJS en un ArrayBuffer JavaScript?
javascript
node.js
binary
buffer
arraybuffer
Drake Amara
la source
la source
Array
. Donc, pour stocker de nombreux flottants, vous avez besoin deFloat32Array
4 octets. Et si vous voulez une sérialisation rapide de ces flottants dans un fichier, vous en avez besoinBuffer
, car la sérialisation vers JSON prend des années.Réponses:
Les instances de
Buffer
sont également des instances deUint8Array
dans node.js 4.x et supérieur. Ainsi, la solution la plus efficace consiste à accéderbuf.buffer
directement à la propriété, selon https://stackoverflow.com/a/31394257/1375574 . Le constructeur Buffer prend également un argument ArrayBufferView si vous devez aller dans l'autre direction.Notez que cela ne créera pas de copie, ce qui signifie que les écritures dans n'importe quel ArrayBufferView écriront dans l'instance Buffer d'origine.
Dans les anciennes versions, node.js a à la fois ArrayBuffer dans le cadre de la v8, mais la classe Buffer fournit une API plus flexible. Pour lire ou écrire dans un ArrayBuffer, il vous suffit de créer une vue et de copier.
De Buffer à ArrayBuffer:
De ArrayBuffer à Buffer:
la source
size&0xfffffffe
, copiez les entiers 32 bits, puis, s'il reste 1 octet, copiez l'entier 8 bits, si 2 octets, copiez l'entier 16 bits, et si 3 octets, copiez les entiers 16 bits et 8 bits.ab
retourné? Il n'y a rien avecab
? Je reçois toujours{}
en conséquence.slice()
méthode retourne un nouveauArrayBuffer
dont le contenu est une copie desArrayBuffer
octets de this de begin, inclusive, up to end, exclusive.' - MDNArrayBuffer.prototype.slice()
Aucune dépendance, plus rapide, Node.js 4.x et versions ultérieures
Buffer
s sont desUint8Array
s, il vous suffit donc de découper (copier) sa région du supportArrayBuffer
.Les
slice
trucs et offset sont nécessaires car les petitsBuffer
s (moins de 4 Ko par défaut, la moitié de la taille du pool ) peuvent être des vues sur un partageArrayBuffer
. Sans découpage, vous pouvez vous retrouver avec unArrayBuffer
contenant des données d'un autreBuffer
. Voir l' explication dans la documentation .Si vous en avez finalement besoin
TypedArray
, vous pouvez en créer un sans copier les données:Aucune dépendance, vitesse modérée, toute version de Node.js
Utilisez la réponse de Martin Thomson , qui s'exécute dans le temps O (n) . (Voir aussi mes réponses aux commentaires sur sa réponse sur les non-optimisations. L'utilisation d'un DataView est lente. Même si vous devez inverser des octets, il existe des moyens plus rapides de le faire.)
Dépendance, rapide, Node.js ≤ 0,12 ou iojs 3.x
Vous pouvez utiliser https://www.npmjs.com/package/memcpy pour aller dans les deux sens (Buffer vers ArrayBuffer et retour). C'est plus rapide que les autres réponses publiées ici et c'est une bibliothèque bien écrite. Les nœuds 0.12 à iojs 3.x nécessitent le fork de ngossen (voir ceci ).
la source
.byteLength
et.byteOffset
documentés?var ab = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
m'a sauvé la journée"From ArrayBuffer to Buffer" pourrait être fait de cette façon:
la source
Une façon plus rapide de l'écrire
Cependant, cela semble fonctionner environ 4 fois plus lentement que la fonction toArrayBuffer suggérée sur un tampon avec 1024 éléments.
la source
Buffer
sont également des instances deUint8Array
dans Node.js 4.x et supérieur. Pour les versions inférieures de Node.js, vous devez implémenter unetoArrayBuffer
fonction.1. A
Buffer
est juste une vue pour regarder dans un fichierArrayBuffer
.A
📜 Node.js 9.4.0Buffer
, en fait, est aFastBuffer
, quiextends
(hérite de)Uint8Array
, qui est une vue d' unité d'octet («accesseur partiel») de la mémoire réelle, anArrayBuffer
./lib/buffer.js#L65-L73
2. La taille d'un
ArrayBuffer
et la taille de sa vue peuvent varier.Raison n ° 1:
Buffer.from(arrayBuffer[, byteOffset[, length]])
.Avec
Buffer.from(arrayBuffer[, byteOffset[, length]])
, vous pouvez créer unBuffer
avec en spécifiant son sousArrayBuffer
- jacent ainsi que la position et la taille de la vue.Raison n ° 2:
FastBuffer
l'allocation de mémoire de.Il alloue la mémoire de deux manières différentes en fonction de la taille.
ArrayBuffer
qui correspond exactement à la mémoire requise./lib/buffer.js#L306-L320
📜 Node.js 9.4.0/lib/buffer.js#L98-L100
Qu'entendez-vous par « pool de mémoire »?
Un pool de mémoire est un bloc de mémoire pré-alloué de taille fixe pour conserver des blocs de mémoire de petite taille pendant
Buffer
s. Son utilisation permet de maintenir les blocs de mémoire de petite taille étroitement ensemble, évitant ainsi la fragmentation causée par la gestion séparée (allocation et désallocation) des blocs de mémoire de petite taille.Dans ce cas, les pools de mémoire sont des
ArrayBuffer
s dont la taille par défaut est de 8 Kio, ce qui est spécifié dansBuffer.poolSize
. Lorsqu'il doit fournir un bloc de mémoire de petite taille pour aBuffer
, il vérifie si le dernier pool de mémoire dispose de suffisamment de mémoire disponible pour gérer cela; si c'est le cas, il crée unBuffer
qui «visualise» le bloc partiel donné du pool de mémoire, sinon, il crée un nouveau pool de mémoire et ainsi de suite.Vous pouvez accéder au sous-jacent
ArrayBuffer
d'unBuffer
. La propriétéBuffer
s (c'est-à-dire héritée de ) la détient. Un « petit » de propriété est un qui représente l'ensemble du pool de mémoire. Donc, dans ce cas, le et le varient en taille.buffer
Uint8Array
Buffer
buffer
ArrayBuffer
ArrayBuffer
Buffer
3. Nous devons donc extraire la mémoire qu'il « visualise ».
An
ArrayBuffer
est de taille fixe, nous devons donc l'extraire en faisant une copie de la pièce. Pour ce faire, nous utilisonsBuffer
labyteOffset
propriété et lalength
propriété de , qui sont héritées deUint8Array
, et laArrayBuffer.prototype.slice
méthode , qui fait une copie d'une partie d'un fichierArrayBuffer
. Laslice()
méthode -ing ici a été inspirée par @ZachB .4. Amélioration des performances
Si vous utilisez les résultats en lecture seule ou si
Buffer
vous pouvez modifier le contenu des entrées , vous pouvez éviter une copie inutile de la mémoire.la source
obtain_arraybuffer
:buf.buffer.subarray
ne semble pas exister. Voulez-vous direbuf.buffer.slice
ici?ArrayBuffer.prototype.slice
et modifié plus tard enUint8Array.prototype.subarray
. Oh, et je l'ai mal fait. Probablement un peu confus à l'époque. Tout va bien maintenant grâce à vous.Utilisez le paquet excellent NPM suivant:
to-arraybuffer
.Ou vous pouvez le mettre en œuvre vous-même. Si votre tampon est appelé
buf
, procédez comme suit:la source
Vous pouvez considérer un
ArrayBuffer
comme un fichier tapéBuffer
.An a
ArrayBuffer
donc toujours besoin d'un type (appelé "Array Buffer View"). En règle générale, la vue de la mémoire tampon du tableau a un type deUint8Array
ouUint16Array
.Il y a un bon article de Renato Mangini sur la conversion entre un ArrayBuffer et une String .
J'ai résumé les parties essentielles dans un exemple de code (pour Node.js). Il montre également comment convertir entre le typé
ArrayBuffer
et le non typéBuffer
.la source
J'ai essayé ce qui précède pour un Float64Array et cela ne fonctionnait tout simplement pas.
J'ai fini par réaliser que vraiment les données devaient être lues «DANS» la vue en morceaux corrects. Cela signifie lire 8 octets à la fois à partir du tampon source.
Bref, c'est ce avec quoi j'ai fini ...
la source
Buffer.read*
méthodes sont toutes lentes également.Ce proxy exposera le tampon comme l'un des TypedArrays, sans aucune copie. :
https://www.npmjs.com/package/node-buffer-as-typedarray
Cela ne fonctionne que sur LE, mais peut être facilement porté vers BE. De plus, je n'ai jamais eu à tester l'efficacité de cette méthode.
la source
Il existe maintenant un package npm très utile pour cela:
buffer
https://github.com/feross/bufferIl tente de fournir une API identique à 100% à l'API Buffer du nœud et autorise:
et quelques autres.
la source
NodeJS, à un moment donné (je pense que c'était v0.6.x) avait le support ArrayBuffer. J'ai créé une petite bibliothèque pour l'encodage et le décodage base64 ici , mais depuis la mise à jour vers la v0.7, les tests (sur NodeJS) échouent. Je pense créer quelque chose qui normalise cela, mais jusque-là, je suppose que le natif de Node
Buffer
devrait être utilisé.la source
J'ai déjà mis à jour mon nœud vers la version 5.0.0 et je travaille avec ceci:
Je l'utilise pour vérifier mon image disque vhd.
la source
toArrayBuffer(new Buffer([1,2,3]))
->['01', '02', '03']
- cela renvoie un tableau de chaînes, pas des entiers / octets.