Necesito hacer un análisis de archivos de registro grandes (5-10 Gb) en Javascript / Node.js (estoy usando Cube).
El logline se parece a:
10:00:43.343423 I'm a friendly log message. There are 5 cats, and 7 dogs. We are in state "SUCCESS".
Hay que leer cada línea, hacer un poco de análisis (por ejemplo, pelar hacia fuera 5
, 7
y SUCCESS
), entonces bombear estos datos en Cubo ( https://github.com/square/cube ) usando su cliente de JS.
En primer lugar, ¿cuál es la forma canónica en Node de leer un archivo, línea por línea?
Parece ser una pregunta bastante común en línea:
- http://www.quora.com/What-is-the-best-way-to-read-a-file-line-by-line-in-node-js
- ¿Leer un archivo una línea a la vez en node.js?
Muchas de las respuestas parecen apuntar a un montón de módulos de terceros:
- https://github.com/nickewing/line-reader
- https://github.com/jahewson/node-byline
- https://github.com/pkrumins/node-lazy
- https://github.com/Gagle/Node-BufferedReader
Sin embargo, esto parece una tarea bastante básica; seguramente, hay una forma simple dentro de stdlib para leer en un archivo de texto, línea por línea.
En segundo lugar, necesito procesar cada línea (por ejemplo, convertir la marca de tiempo en un objeto de fecha y extraer campos útiles).
¿Cuál es la mejor manera de hacer esto, maximizando el rendimiento? ¿Hay alguna forma que no bloquee la lectura de cada línea o el envío a Cube?
En tercer lugar, supongo que usar divisiones de cadenas, y el equivalente en JS de contains (IndexOf! = -1?) Será mucho más rápido que las expresiones regulares. ¿Alguien ha tenido mucha experiencia en analizar cantidades masivas de datos de texto en Node.js?
Saludos, Victor
fuente
Respuestas:
Busqué una solución para analizar archivos muy grandes (gbs) línea por línea usando una secuencia. Todas las bibliotecas y ejemplos de terceros no se adaptaron a mis necesidades, ya que procesaron los archivos no línea por línea (como 1, 2, 3, 4 ..) o leyeron todo el archivo en la memoria.
La siguiente solución puede analizar archivos muy grandes, línea por línea, usando stream & pipe. Para las pruebas utilicé un archivo de 2,1 gb con 17.000.000 registros. El uso de RAM no superó los 60 mb.
Primero, instale el paquete event-stream :
Luego:
¡Por favor déjame saber cómo va!
fuente
console.log(lineNr)
después de la última línea de su código, no mostrará el recuento de líneas final porque el archivo se lee de forma asincrónica.s.end();
readline
módulo es una molestia. No se detiene y estaba causando fallas cada vez después de 40-50 millones. Perdido un día. Muchas gracias por la respuesta. Esta funciona perfectamentePuede utilizar el
readline
paquete incorporado , consulte los documentos aquí . Utilizo stream para crear un nuevo flujo de salida.Los archivos grandes tardarán algún tiempo en procesarse. Dime si funciona.
fuente
readline
, ¿es posible pausar / reanudar el flujo de lectura para realizar acciones asíncronas en el área "hacer cosas"?readline
me estaba dando muchos problemas cuando intenté pausar / reanudar. No pausa la transmisión correctamente, lo que crea muchos problemas si el proceso descendente es más lentoRealmente me gustó la respuesta de @gerard, que en realidad merece ser la respuesta correcta aquí. Hice algunas mejoras:
Aquí está el código:
Básicamente, así es como lo usará:
Probé esto con un archivo CSV de 35GB y funcionó para mí y es por eso que elegí construirlo en la respuesta de @gerard , los comentarios son bienvenidos.
fuente
pause()
llamada, ¿no?Usé https://www.npmjs.com/package/line-by-line para leer más de 1 000 000 de líneas de un archivo de texto. En este caso, la capacidad de RAM ocupada era de 50 a 60 megabytes.
fuente
lr.cancel()
método. Lee las primeras 1000 líneas de un archivo de 5 Gig en 1 ms. ¡¡¡¡Increíble!!!!Además de leer el archivo grande línea por línea, también puede leerlo fragmento a fragmento. Para obtener más información, consulte este artículo.
fuente
if(bytesRead = chunkSize)
:?La documentación de Node.js ofrece un ejemplo muy elegante utilizando el módulo Readline.
Ejemplo: lectura del flujo de archivos línea por línea
fuente
Tuve el mismo problema todavía. Después de comparar varios módulos que parecen tener esta característica, decidí hacerlo yo mismo, es más simple de lo que pensaba.
esencia: https://gist.github.com/deemstone/8279565
Cubre el archivo abierto en un cierre, que
fetchBlock()
devuelto buscará un bloque del archivo, finaliza la división en la matriz (se ocupará del segmento de la última búsqueda).Establecí el tamaño del bloque en 1024 para cada operación de lectura. Esto puede tener errores, pero la lógica del código es obvia, pruébelo usted mismo.
fuente
Nodo por línea utiliza secuencias, por lo que preferiría esa para sus archivos enormes.
para sus conversiones de fecha, usaría moment.js .
para maximizar su rendimiento, podría pensar en utilizar un clúster de software. hay algunos módulos agradables que encajan bastante bien con el módulo de clúster nativo del nodo. me gusta cluster-master de isaacs. por ejemplo, podría crear un grupo de x trabajadores que calculan un archivo.
para comparar divisiones frente a expresiones regulares, use benchmark.js . No lo he probado hasta ahora. benchmark.js está disponible como módulo de nodo
fuente
Basándome en esta respuesta a las preguntas, implementé una clase que puede usar para leer un archivo sincrónicamente línea por línea
fs.readSync()
. Puede hacer esta "pausa" y "reanudar" mediante unaQ
promesa (jQuery
parece requerir un DOM, por lo que no puede ejecutarlonodejs
):fuente
fuente
He creado un módulo de nodo para leer archivos grandes de forma asincrónica, texto o JSON. Probado en archivos grandes.
Simplemente guarde el archivo como file-reader.js y utilícelo así:
fuente