¿Cómo puedo convertir un búfer binario NodeJS en un ArrayBuffer de JavaScript?
javascript
node.js
binary
buffer
arraybuffer
Drake Amara
fuente
fuente
Array
. Por lo tanto, para almacenar muchos flotadores, necesitaFloat32Array
4 bytes. Y si desea una serialización rápida de esos flotadores en un archivo, necesita unBuffer
, ya que la serialización a JSON lleva años.Respuestas:
Las instancias de
Buffer
también son instancias deUint8Array
en node.js 4.xy superior. Por lo tanto, la solución más eficiente es acceder a labuf.buffer
propiedad directamente, según https://stackoverflow.com/a/31394257/1375574 . El constructor Buffer también toma un argumento ArrayBufferView si necesita ir en la otra dirección.Tenga en cuenta que esto no creará una copia, lo que significa que las escrituras en cualquier ArrayBufferView se escribirán en la instancia original de Buffer.
En versiones anteriores, node.js tiene ArrayBuffer como parte de v8, pero la clase Buffer proporciona una API más flexible. Para leer o escribir en un ArrayBuffer, solo necesita crear una vista y copiarla.
De Buffer a ArrayBuffer:
De ArrayBuffer a Buffer:
fuente
size&0xfffffffe
, copie enteros de 32 bits, luego, si queda 1 byte, copie un entero de 8 bits, si tiene 2 bytes, copie un entero de 16 bits, y si tiene 3 bytes, copie un entero de 16 bits y 8 bits.ab
devuelve? No hay nada hecho conab
? Siempre consigo{}
como resultado.slice()
método devuelve un nuevoArrayBuffer
cuyo contenido es una copia deArrayBuffer
los bytes de este desde inicio, inclusivo, hasta el final, exclusivo' - MDNArrayBuffer.prototype.slice()
Sin dependencias, más rápido, Node.js 4.xy posterior
Buffer
s sonUint8Array
s, por lo que solo necesita cortar (copiar) su región del respaldoArrayBuffer
.El material
slice
y el desplazamiento son necesarios porque los pequeñosBuffer
s (menos de 4 kB por defecto, la mitad del tamaño del grupo ) pueden ser vistas en un espacio compartidoArrayBuffer
. Sin segmentar, puede terminar conArrayBuffer
datos que contienen de otroBuffer
. Ver explicación en los documentos .Si finalmente necesita un
TypedArray
, puede crear uno sin copiar los datos:Sin dependencias, velocidad moderada, cualquier versión de Node.js
Use la respuesta de Martin Thomson , que se ejecuta en O (n) . (Consulte también mis respuestas a los comentarios sobre su respuesta sobre las no optimizaciones. El uso de un DataView es lento. Incluso si necesita voltear bytes, hay formas más rápidas de hacerlo).
Dependencia, rápida, Node.js ≤ 0.12 o iojs 3.x
Puede usar https://www.npmjs.com/package/memcpy para ir en cualquier dirección (Buffer to ArrayBuffer y viceversa). Es más rápido que las otras respuestas publicadas aquí y es una biblioteca bien escrita. Los nodos 0.12 a iojs 3.x requieren la bifurcación de ngossen (vea esto ).
fuente
.byteLength
y.byteOffset
documentados?var ab = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
me salvó el día"De ArrayBuffer a Buffer" podría hacerse de esta manera:
fuente
Una forma más rápida de escribirlo.
Sin embargo, esto parece ejecutarse aproximadamente 4 veces más lento que la función toArrayBuffer sugerida en un búfer con 1024 elementos.
fuente
Buffer
también son instancias deUint8Array
Node.js 4.xy superior. Para versiones inferiores de Node.js, debe implementar unatoArrayBuffer
función.1. A
Buffer
es solo una vista para mirar unArrayBuffer
.A
📜 Node.js 9.4.0Buffer
, de hecho, es unFastBuffer
, queextends
(hereda de)Uint8Array
, que es una vista de unidad de octeto ("acceso parcial") de la memoria real, unArrayBuffer
./lib/buffer.js#L65-L73
2. El tamaño de an
ArrayBuffer
y el tamaño de su vista pueden variar.Razón # 1:
Buffer.from(arrayBuffer[, byteOffset[, length]])
.Con
Buffer.from(arrayBuffer[, byteOffset[, length]])
, puede crear unBuffer
con especificar su subyacenteArrayBuffer
y la posición y el tamaño de la vista.Razón # 2:
FastBuffer
asignación de memoria de.Asigna la memoria de dos formas diferentes según el tamaño.
ArrayBuffer
que se ajusta exactamente a la memoria requerida./lib/buffer.js#L306-L320
📜 Node.js 9.4.0/lib/buffer.js#L98-L100
¿Qué quiere decir con un " grupo de memoria "?
Un grupo de memoria es un bloque de memoria preasignado de tamaño fijo para mantener fragmentos de memoria de tamaño pequeño durante
Buffer
s. Su uso mantiene los fragmentos de memoria de pequeño tamaño muy juntos, por lo que evita la fragmentación. causada por la administración separada (asignación y desasignación) de fragmentos de memoria de pequeño tamaño.En este caso, las agrupaciones de memoria son
ArrayBuffer
s cuyo tamaño es de 8 KiB de forma predeterminada, que se especifica enBuffer.poolSize
. Cuando se trata de proporcionar un fragmento de memoria de tamaño pequeño para unBuffer
, comprueba si el último grupo de memoria tiene suficiente memoria disponible para manejar esto; si es así, crea unBuffer
que "ve" el fragmento parcial dado del grupo de memoria, de lo contrario, crea un nuevo grupo de memoria y así sucesivamente.Puede acceder al subyacente
ArrayBuffer
de aBuffer
. ElBuffer
'sbuffer
de propiedad (es decir, heredado deUint8Array
) la sostiene. Un “pequeño”Buffer
'sbuffer
establecimiento es elArrayBuffer
que representa la totalidad del bloque de memoria. Entonces, en este caso, elArrayBuffer
y elBuffer
varía en tamaño.3. Entonces necesitamos extraer la memoria que " ve ".
Un
ArrayBuffer
tamaño es fijo, por lo que debemos extraerlo haciendo una copia de la pieza. Para hacer esto, utilizamosBuffer
labyteOffset
propiedad y lalength
propiedad , que se heredanUint8Array
, y elArrayBuffer.prototype.slice
método , que hace una copia de una parte de unArrayBuffer
. Elslice()
método -ing aquí fue inspirado por @ZachB .4. Mejora del rendimiento
Si va a utilizar los resultados como de solo lectura, o está bien modificar el
Buffer
contenido de la entrada , puede evitar la copia innecesaria de la memoria.fuente
obtain_arraybuffer
:buf.buffer.subarray
no parece existir. ¿Quisiste decirbuf.buffer.slice
aquí?ArrayBuffer.prototype.slice
y luego lo modifiquéUint8Array.prototype.subarray
. Ah, y lo hice mal. Probablemente se confundió un poco en ese entonces. Todo está bien ahora gracias a ti.Utiliza el siguiente paquete excelente NPM:
to-arraybuffer
.O bien, puede implementarlo usted mismo. Si se llama a su búfer
buf
, haga esto:fuente
Puedes pensar en un
ArrayBuffer
como mecanografiadoBuffer
.Una
ArrayBuffer
, por tanto, siempre tiene un tipo (el denominado "Matriz de búfer Ver"). Normalmente, la Vista de búfer de matriz tiene un tipo deUint8Array
oUint16Array
.Hay un buen artículo de Renato Mangini sobre la conversión entre un ArrayBuffer y una Cadena .
He resumido las partes esenciales en un ejemplo de código (para Node.js). También muestra cómo convertir entre los mecanografiados
ArrayBuffer
y los no tipificadosBuffer
.fuente
Intenté lo anterior para un Float64Array y simplemente no funcionó.
Terminé dándome cuenta de que realmente los datos debían leerse 'EN' la vista en fragmentos correctos. Esto significa leer 8 bytes a la vez desde el Buffer de origen.
De todos modos esto es con lo que terminé ...
fuente
Buffer.read*
métodos también son lentos.Este proxy expondrá el búfer como cualquiera de los TypedArrays, sin ninguna copia. :
https://www.npmjs.com/package/node-buffer-as-typedarray
Solo funciona en LE, pero se puede portar fácilmente a BE. Además, nunca pude probar qué tan eficiente es esto.
fuente
Ahora hay un paquete npm muy útil para esto:
buffer
https://github.com/feross/bufferIntenta proporcionar una API que sea 100% idéntica a la API de búfer del nodo y permita:
y pocos mas.
fuente
NodeJS, en un momento (creo que fue v0.6.x) tenía soporte para ArrayBuffer. Creé una pequeña biblioteca para la codificación y decodificación base64 aquí , pero desde la actualización a v0.7, las pruebas (en NodeJS) fallan. Estoy pensando en crear algo que normalice esto, pero hasta entonces, supongo que se
Buffer
debe usar el nativo de Node .fuente
Ya actualicé mi nodo a la Versión 5.0.0 y trabajo con esto:
Lo uso para verificar la imagen de mi disco vhd.
fuente
toArrayBuffer(new Buffer([1,2,3]))
->['01', '02', '03']
- esto devuelve una matriz de cadenas, no enteros / bytes.