Volver al blog

Gestión de CSV en Node.js usando Node-CSV

Gestión de CSV en Node.js usando Node-CSV

Un CSV es un archivo de texto plano que almacena datos en formato tabular. En la mayoría de los casos, los archivos CSV utilizan comas (,) como delimitador, de ahí el nombre CSV (valores separados por comas). Se utiliza en situaciones donde la compatibilidad de los datos es una preocupación, ya que los CSV se pueden abrir con cualquier editor de texto, aplicaciones de hojas de cálculo y otras herramientas especializadas. De hecho, muchos lenguajes de programación ofrecen soporte integrado para CSV.

En esta guía, aprenderemos sobre el uso de CSV en una aplicación de Node.js de muestra.

CSV en Node.js

Node.js es un entorno de ejecución de JavaScript de código abierto y multiplataforma. Se ha convertido en uno de los backends más populares que impulsan numerosos servicios web en todo el internet. Incluso grandes empresas como Netflix y Uber utilizan Node.js para impulsar sus servicios.

Node.js también tiene numerosos módulos disponibles para ser implementados para agregar funcionalidad adicional a un proyecto. Cuando se trata de CSV, hay muchos módulos disponibles para usar, por ejemplo, node-csv, fast-csv, y papaparse etc.

Como sugiere el título de la guía, vamos a utilizar node-csv para leer archivos CSV utilizando flujos (streams) de Node.js. También demostraremos cómo trabajar con los datos analizados, por ejemplo, transfiriendo los datos a una base de datos SQLite .

Requisitos previos

Paso 1 – Instalación del software necesario

Para esta guía, he creado un servidor ligero que ejecuta Ubuntu 22.04 LTS (conectado a través de SSH):

Ahora, instalaremos Node.js y SQLite en él.

  • Instalación de Node.js LTS

Node.js está disponible directamente desde los repositorios oficiales de paquetes de Ubuntu. Sin embargo, no es la versión más actualizada. Es por eso que vamos a confiar en un repositorio de terceros (Nodesource) para obtener los últimos paquetes de Node.js.

Agregue el repositorio para Node.js LTS:

Ahora, instale Node.js LTS:

  • Instalar SQLite

Instalaremos SQLite directamente desde los repositorios de paquetes de Ubuntu. Ejecute los siguientes comandos:

Paso 2 – Configuración del directorio del proyecto

En esta sección, prepararemos un directorio dedicado para nuestro proyecto. Albergará todos los archivos del proyecto junto con módulos adicionales.

Cree un nuevo directorio:

Navegue dentro del directorio:

A continuación, ejecute el siguiente comando para declarar el directorio como un proyecto npm :

Una vez inicializada la carpeta del proyecto, podemos comenzar a instalar los paquetes y módulos necesarios. Primero, vamos a instalar node-csv:

El módulo node-csv es en realidad una colección de varios otros módulos: csv-generate, csv-parse (para analizar archivos CSV), csv-stringify (para escribir datos en CSV) y stream-transform.

A continuación, necesitamos el módulo para comunicarnos con SQLite. El siguiente comando instalará el módulo node-sqlite3 :

El componente que necesitamos para nuestro proyecto es un archivo CSV. Para fines de demostración, utilizaremos el archivo CSV de migración de Nueva Zelanda:

Echemos un vistazo rápido al contenido del archivo:

Aquí,

  • La primera línea describe los nombres de las columnas.

  • Las líneas siguientes contienen los valores para estos campos.

  • Cada fila está separada por una nueva línea (\n).

  • Cada punto de datos está separado por una coma (,).

Sin embargo, CSV no se limita a usar comas como delimitador. Otros delimitadores comunes incluyen dos puntos (:), puntos y comas (;) y tabulaciones (\td).

Paso 3 – Lectura de CSV

En esta sección, demostraremos la implementación de un programa de ejemplo que lee y analiza datos del archivo CSV.

Crea un nuevo archivo JavaScript:

Abre el archivo en tu editor de texto favorito:

Primero, vamos a importar los módulos fs y csv-parse:

Aquí,

  • Primero, a la variable fs se le asigna el objeto fs que devuelve el método require() de Node.js al importar el módulo.

  • A continuación, el método parse se extrae del objeto devuelto por el método require() en la variable parse utilizando la sintaxis de desestructuración.

A continuación, vamos a agregar código para leer el archivo CSV:

Aquí,

  • Estamos invocando el método createReadStream() del módulo fs y pasando como argumento el archivo CSV que queremos leer. Luego, crea un flujo de lectura (readable stream) dividiendo el archivo más grande en fragmentos más pequeños.

  • Después de crear el flujo, el método pipe() reenvía fragmentos de los datos del flujo a otro flujo. Este nuevo flujo se crea al invocar el método parse() del módulo csv-module.

  • El módulo csv-module despliega un flujo de transformación de lectura/escritura que toma un fragmento de datos y lo transforma en otra forma.

  • El método parse() acepta objetos con propiedades. El objeto procesa adicionalmente los datos analizados. Aquí, el objeto toma las siguientes propiedades:

    • delimiter: El carácter delimitador para separar valores. En el caso de nuestro CSV de destino, es la coma (,).

    • from_line: El número de líneas desde donde el analizador comenzará a analizar. Con el valor dado de 2, el analizador omitirá la línea 1 y comenzará en la línea 2. Con esta disposición, evitamos que los nombres de las columnas se integren en los datos analizados.

A continuación, vamos a adjuntar un evento de flujo utilizando el método on() de Node.js:

Aquí,

  • Al emitir un evento determinado, un evento de flujo permite que un método consuma un fragmento de datos.

  • Cuando los datos analizados por el método parse() están listos para ser consumidos, se activa el evento data.

  • Para acceder a los datos, pasamos una función de devolución de llamada al método on() que toma un parámetro row.

  • El parámetro row es un fragmento de datos en forma de matriz (resultado del análisis).

  • Finalmente, los datos se registran en la consola utilizando console.log().

Para finalizar el programa, vamos a agregar eventos de flujo adicionales para manejar errores e imprimir un mensaje de éxito cuando se hayan consumido todos los datos del archivo CSV. Actualiza el código de la siguiente manera:

Aquí,

  • El evento end se emite cuando se consumen todos los datos del archivo CSV. Da como resultado la llamada al console.log() método que imprime un mensaje de éxito.

  • El evento error se emite al encontrar un error al analizar los datos CSV. Da como resultado la llamada al console.log() método que imprime un mensaje de error.

El código final debería verse así:

Guarde el archivo y cierre el editor. Ahora estamos listos para ejecutar el programa. Ejecútelo usando Node.js:

La salida debería verse algo así:

Tenga en cuenta que los datos se consumen, transforman y se imprimen en la consola. Como es un proceso continuo, parecerá que los datos se están descargando en lugar de imprimir la salida toda de una vez.

Paso 4 – Transferencia de datos CSV a una base de datos

Hasta ahora, hemos aprendido cómo analizar un archivo CSV usando node-csv. Esta sección demostrará la transferencia de los datos analizados a una base de datos (SQLite).

Cree un nuevo archivo JavaScript para interactuar con la base de datos:

Ahora, abra el archivo en un editor de texto:

Comenzaremos nuestro programa con el siguiente código:

Aquí,

  • En la primera línea, estamos importando el fs módulo.

  • En la tercera línea, la variable filepath contiene la ruta de la base de datos SQLite.

  • En este punto, la base de datos aún no existe. Sin embargo, será necesaria al trabajar con node-sqlite3.

A continuación, agregue las siguientes líneas para establecer una conexión con la base de datos SQLite:

Aquí,

  • El método connectoToDatabase() establece una conexión con la base de datos.

  • Dentro de connectToDatabase(), estamos invocando el existsSync() método del módulo fs dentro de una sentencia if. La sentencia if verifica la existencia de la base de datos en la ubicación especificada.

    • Si la evaluación de la condición es true, entonces la Database() clase del node-sqlite3 módulo se instancia. Una vez establecida la conexión, la función devuelve un objeto y finaliza.

    • Si la evaluación de la condición es false (la base de datos no existe), entonces la ejecución saltará al bloque else. Allí, la Database() clase se iniciará con dos argumentos: una ruta al archivo de la base de datos y un callback.

Básicamente, la base de datos se creará si no existe. Sin embargo, si ocurre algún error durante el proceso de creación, establecerá el objeto error e imprimirá el mensaje de error.

A continuación, vamos a introducir código para crear una tabla si la base de datos no existe:

Aquí,

  • La función connectToDatabase() invoca la función createTable() que acepta el objeto almacenado en db como argumento.

  • Fuera de connectToDatabase(), definimos el método createTable() que acepta el objeto de conexión db como parámetro.

  • El método exec() en db toma una sentencia SQL como argumento. Dentro de esta sentencia SQL, definimos la creación de una tabla migration con 7 columnas, cada una correspondiente a los encabezados de columna en el archivo migration_data.csv .

  • Finalmente, estamos invocando connectToDatabase() método y exportando el objeto de conexión que devuelve para que podamos usarlo en otros archivos.

Guarde el archivo y cierre el editor.

A continuación, vamos a crear otro programa para insertar los datos analizados en la base de datos:

Introduzca el siguiente código en insert_data.js:

Aquí,

  • Estamos almacenando el objeto de conexión obtenido de csv-to-sqlite3.js en la variable db.

  • Dentro de la función de devolución de llamada (callback) del evento data (asociada al flujo del módulo fs), estamos invocando el serialize() método en el objeto de conexión. Asegura que una sentencia SQL termine de ejecutarse antes de que comience la siguiente, evitando condiciones de carrera en la base de datos (el sistema ejecutando operaciones competidoras simultáneamente).

  • El serialize() acepta tres argumentos:

    • El primer argumento es la sentencia SQL.

    • El segundo argumento es un array.

    • El tercer argumento es una función de devolución de llamada (callback) que se ejecuta cuando los datos se insertan con éxito o sin éxito en la base de datos.

Estamos listos para ejecutar el programa. Ejecute insert_data.js usando Node.js:

Dependiendo del rendimiento del sistema, el proceso puede tardar algún tiempo en finalizar. Sin embargo, al completarse, la salida debería verse algo así:

Paso 5 – Escritura de datos en CSV

Después de la última sección, tenemos una base de datos que contiene todos los registros que analizamos de migration_data.csv. En esta sección, vamos a leer los datos de la base de datos y a escribirlos en un archivo CSV separado.

Cree un nuevo archivo JavaScript para almacenar el programa:

Primero, agregue las siguientes líneas para importar fs y csv-stringify  junto con el objeto de conexión de la base de datos de csv-to-sqlite3.js:

A continuación, vamos a añadir una variable que contiene el nombre del archivo CSV en el que escribir junto con un flujo de escritura:

Aquí,

  • El método createWriteStream() toma como argumento el nombre del archivo en el que escribir. Vamos a nombrar al archivo saved_from_db.csv.

  • La variable column almacena un array que contiene todos los nombres de la cabecera para los datos CSV.

A continuación, añade las siguientes líneas de código para leer datos de la base de datos y escribirlos en saved_from_db.csv:

Aquí,

  • Invocamos el método stringify() con un objeto como argumento. Esto da como resultado un flujo de transformación que convierte los datos de un objeto al formato CSV. El objeto pasado a stringify() tiene dos propiedades:

    • header: Acepta un valor booleano. Si el valor es true, entonces se genera una cabecera.

    • columns: Acepta un array que contiene los nombres de las columnas que se escribirán en la primera línea del archivo CSV si header es true.

  • El método each() de la conexión csv-to-sqlite3 se invoca con dos argumentos: la sentencia SQL (que lee datos de la base de datos) y un callback (que maneja el éxito/error).

  • En cada iteración de each(), pipe() (desde el flujo stringifier) comienza a enviar datos en fragmentos al flujo de escritura writableStream. Cada fragmento de datos se escribe luego en saved_from_db.csv.

  • Cuando todos los datos se han escrito en el archivo CSV, se muestra un mensaje de éxito en la pantalla de la consola.

El código final debería verse así:

Guarde el archivo y cierre el editor. Ahora podemos ejecutar el programa usando Node.js:

Para confirmar si los datos se exportaron correctamente, verifique el contenido de saved_from_db.csv:

Consideraciones finales

En esta guía, demostramos cómo trabajar con archivos CSV en Node.js utilizando los módulos node-csv y node-sqlite3. Creamos múltiples programas para realizar diversas tareas, por ejemplo, analizar datos de un CSV, insertar los datos en una base de datos SQLite y escribir datos en un nuevo archivo CSV.

Esta guía demuestra solo una pequeña parte de la capacidad del node-csv módulo. Obtenga más información sobre todas sus funciones en CSV Project. Para obtener más información sobre node-sqlite3, consulte la documentación oficial en GitHub. Otro módulo que vale la pena mencionar es event-stream para simplificar el trabajo con streams.

¿Le interesa hacer crecer aún más su proyecto de Node.js? Aquí tiene algunos tutoriales de Node.js que debería consultar:

¡Feliz programación!

author

Preslav Dobrev

Autor · CloudSigma

Preslav Dobrev es diseñador creativo en CloudSigma, centrado en una identidad empresarial coherente mediante el uso de canales de marketing tradicionales e innovadores. Es experto en fusionar la visión artística con el marketing estratégico para crear narrativas de marca impactantes.

Comentarios

Aún no hay comentarios. Sea el primero.