¿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, necesitaFloat32Array4 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
Buffertambién son instancias deUint8Arrayen node.js 4.xy superior. Por lo tanto, la solución más eficiente es acceder a labuf.bufferpropiedad 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.abdevuelve? No hay nada hecho conab? Siempre consigo{}como resultado.slice()método devuelve un nuevoArrayBuffercuyo contenido es una copia deArrayBufferlos bytes de este desde inicio, inclusivo, hasta el final, exclusivo' - MDNArrayBuffer.prototype.slice()Sin dependencias, más rápido, Node.js 4.xy posterior
Buffers sonUint8Arrays, por lo que solo necesita cortar (copiar) su región del respaldoArrayBuffer.El material
slicey el desplazamiento son necesarios porque los pequeñosBuffers (menos de 4 kB por defecto, la mitad del tamaño del grupo ) pueden ser vistas en un espacio compartidoArrayBuffer. Sin segmentar, puede terminar conArrayBufferdatos 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
.byteLengthy.byteOffsetdocumentados?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
Buffertambién son instancias deUint8ArrayNode.js 4.xy superior. Para versiones inferiores de Node.js, debe implementar unatoArrayBufferfunción.1. A
Bufferes 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-L732. El tamaño de an
ArrayBuffery el tamaño de su vista pueden variar.Razón # 1:
Buffer.from(arrayBuffer[, byteOffset[, length]]).Con
Buffer.from(arrayBuffer[, byteOffset[, length]]), puede crear unBuffercon especificar su subyacenteArrayBuffery la posición y el tamaño de la vista.Razón # 2:
FastBufferasignación de memoria de.Asigna la memoria de dos formas diferentes según el tamaño.
- Si el tamaño es menor que la mitad del tamaño de un grupo de memoria y no es 0 ("pequeño") : utiliza un grupo de memoria para preparar la memoria requerida.
- De lo contrario : crea un dedicado
📜 Node.js 9.4.0ArrayBufferque 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
Buffers. 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
ArrayBuffers 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 unBufferque "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
ArrayBufferde aBuffer. ElBuffer'sbufferde propiedad (es decir, heredado deUint8Array) la sostiene. Un “pequeño”Buffer'sbufferestablecimiento es elArrayBufferque representa la totalidad del bloque de memoria. Entonces, en este caso, elArrayBuffery elBuffervaría en tamaño.3. Entonces necesitamos extraer la memoria que " ve ".
Un
ArrayBuffertamaño es fijo, por lo que debemos extraerlo haciendo una copia de la pieza. Para hacer esto, utilizamosBufferlabyteOffsetpropiedad y lalengthpropiedad , que se heredanUint8Array, y elArrayBuffer.prototype.slicemé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
Buffercontenido de la entrada , puede evitar la copia innecesaria de la memoria.fuente
obtain_arraybuffer:buf.buffer.subarrayno parece existir. ¿Quisiste decirbuf.buffer.sliceaquí?ArrayBuffer.prototype.slicey 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
ArrayBuffercomo 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 deUint8ArrayoUint16Array.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
ArrayBuffery 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:
bufferhttps://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
Bufferdebe 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.