Terug naar blog

CSV beheren in Node.js met behulp van Node-CSV

CSV beheren in Node.js met behulp van Node-CSV

Een CSV-bestand is een plat tekstbestand dat gegevens in tabelvorm opslaat. In de meeste gevallen gebruiken CSV-bestanden komma's (,) als scheidingsteken, vandaar de naam CSV (Comma Separated Values). Het wordt gebruikt in situaties waarin gegevenscompatibiliteit een rol speelt, aangezien CSV’s geopend kunnen worden met elke teksteditor, spreadsheet-apps en andere gespecialiseerde tools. In feite bieden veel programmeertalen ingebouwde ondersteuning voor CSV.

In deze handleiding leren we hoe we CSV kunnen gebruiken in een voorbeeld-Node.js-applicatie.

CSV in Node.js

Node.js is een open-source en cross-platform JavaScript-runtime-omgeving. Het is een van de meest populaire backends geworden die tal van webdiensten over het hele internet aanstuurt. Zelfs grote bedrijven zoals Netflix en Uber gebruiken Node.js om hun diensten aan te sturen.

Node.js heeft ook tal van modules beschikbaar die kunnen worden ingezet om extra functionaliteit aan een project toe te voegen. Als het om CSV gaat, zijn er veel modules beschikbaar om te gebruiken, bijvoorbeeld node-csv, fast-csv, en papaparse etc.

Zoals de titel van de handleiding suggereert, gaan we node-csv gebruiken om CSV-bestanden te lezen met behulp van Node.js-streams. We zullen ook demonstreren hoe we met de geparseerde gegevens kunnen werken, bijvoorbeeld door de gegevens over te zetten naar een SQLite-database.

Vereisten

Step 1 – Benodigde software installeren

Voor deze handleiding heb ik een lichtgewicht server gemaakt met Ubuntu 22.04 LTS (verbonden via SSH):

Nu zullen we Node.js and SQLite hierop installeren.

  • Node.js LTS installeren

Node.js is rechtstreeks beschikbaar via de officiële Ubuntu-pakketbronnen. Het is echter niet de meest recente versie. Daarom gaan we vertrouwen op een externe repository (Nodesource) om de nieuwste Node.js-pakketten te verkrijgen.

Voeg de repository toe voor Node.js LTS:

Installeer nu Node.js LTS:

  • SQLite installeren

We installeren SQLite rechtstreeks vanuit de Ubuntu-pakketbronnen. Voer de volgende commando's uit:

Step 2 – Projectmap instellen

In dit gedeelte bereiden we een speciale map voor ons project voor. Deze zal alle projectbestanden bevatten, samen met aanvullende modules.

Maak een nieuwe map aan:

Navigeer naar de map:

Voer vervolgens het volgende commando uit om de map te declareren als een npm-project:

Zodra de projectmap is geïnitialiseerd, kunnen we beginnen met het installeren van de benodigde pakketten en modules. Eerst gaan we installerennode-csv:

De node-csv-module is eigenlijk een verzameling van verschillende andere modules: csv-generate, csv-parse (voor het parsen van CSV-bestanden), csv-stringify (voor het schrijven van gegevens naar CSV) en stream-transform.

Vervolgens hebben we de module nodig om met SQLite te communiceren. Het volgende commando installeert de node-sqlite3-module:

Het component dat we nodig hebben voor ons project is een CSV-bestand. Voor demonstratiedoeleinden gaan we het CSV-bestand met migratiegegevens van Nieuw-Zeeland gebruiken:

Laten we snel naar de inhoud van het bestand kijken:

Hier,

  • De eerste regel beschrijft de kolomnamen.

  • De volgende regels bevatten de waarden voor deze velden.

  • Elke rij is gescheiden door een nieuwe regel (\n).

  • Elk datapunt is gescheiden door een komma (,).

CSV is echter niet beperkt tot het gebruik van komma’s als scheidingsteken. Andere veelvoorkomende scheidingstekens zijn dubbele punten (:), puntkomma’s (;) en tabs (\td).

Stap 3 – CSV lezen

In deze sectie demonstreren we het implementeren van een voorbeeldprogramma dat gegevens uit het CSV-bestand leest en parseert.

Maak een nieuw JavaScript-bestand aan:

Open het bestand in je favoriete tekstverwerker:

Eerst gaan we de fs en csv-parse modules importeren:

Hier,

  • Eerst wordt aan de fs variabele het fs object toegewezen dat de Node.js require() methode retourneert bij het importeren van de module.

  • Vervolgens wordt de parse-methode uit het object dat is geretourneerd door de require() methode geëxtraheerd naar de parse-variabele met behulp van de destructuring-syntaxis.

Vervolgens gaan we code toevoegen om het CSV-bestand te lezen:

Hier,

  • We roepen de createReadStream() aan vanuit de fs-module en geven het CSV-bestand dat we willen lezen door als argument. Dit maakt vervolgens een leesbare stream door het grotere bestand in kleinere stukken op te delen.

  • Na het maken van de stream stuurt de pipe() methode delen van de streamgegevens door naar een andere stream. Deze nieuwe stream wordt gemaakt bij het aanroepen van de parse() methode uit de csv-module.

  • De csv-module stelt een leesbare/schrijfbare transformatiestream beschikbaar die een gegevenssegment neemt en dit in een andere vorm transformeert.

  • De parse() methode accepteert objecten met eigenschappen. Het object verwerkt de geparseerde gegevens verder. Hier neemt het object de volgende eigenschappen aan:

    • delimiter: Het scheidingsteken om waarden te scheiden. In het geval van onze doel-CSV is dit een komma (,).

    • from_line: Het aantal regels vanaf waar de parser begint met parseren. Met de opgegeven waarde 2 slaat de parser regel 1 over en begint op regel 2. Met deze opzet voorkomen we dat de kolomnamen in de geparseerde gegevens worden opgenomen.

Vervolgens gaan we een streaming-event koppelen met behulp van de on() methode van Node.js:

Hier,

  • Bij het activeren van een bepaalde gebeurtenis stelt een streaming-event een methode in staat om een deel van de gegevens te consumeren.

  • Wanneer gegevens die zijn geparseerd door de parse() methode klaar zijn om te worden geconsumeerd, activeert dit de data gebeurtenis.

  • Om toegang te krijgen tot de gegevens, geven we een callback door aan de on() methode die een parameter row accepteert.

  • De parameter row is een deel van de gegevens in de vorm van een array (het resultaat van het parseren).

  • Ten slotte worden de gegevens in de console gelogd met behulp van console.log().

Om het programma te voltooien, gaan we extra stream-events toevoegen om fouten af te handelen en een succesbericht af te drukken wanneer alle gegevens in het CSV-bestand zijn verwerkt. Werk de code als volgt bij:

Hier,

  • Het end-event wordt geactiveerd wanneer alle gegevens in het CSV-bestand zijn verwerkt. Dit resulteert in het aanroepen van de console.log() methode die een succesbericht afdrukt.

  • Het error-event wordt geactiveerd wanneer er een fout optreedt tijdens het parseren van de CSV-gegevens. Dit resulteert in het aanroepen van de console.log() methode die een foutmelding afdrukt.

De uiteindelijke code zou er als volgt uit moeten zien:

Sla het bestand op en sluit de editor. We zijn nu klaar om het programma uit te voeren. Voer het uit met Node.js:

De uitvoer zou er ongeveer zo uit moeten zien:

Merk op dat de gegevens worden verwerkt, getransformeerd en op de console worden afgedrukt. Omdat het een continu proces is, zal het lijken alsof de gegevens worden gedownload in plaats van dat de uitvoer in één keer wordt afgedrukt.

Stap 4 – CSV-gegevens overdragen naar een database

Tot nu toe hebben we geleerd hoe we een CSV-bestand kunnen parseren met node-csv. In deze sectie wordt gedemonstreerd hoe u de geparseerde gegevens overdraagt naar een database (SQLite).

Maak een nieuw JavaScript-bestand om met de database te communiceren:

Open nu het bestand in een teksteditor:

We beginnen ons programma met de volgende code:

Hier,

  • In de eerste regel importeren we de fs module.

  • In de derde regel bevat de variabele filepath het pad van de SQLite-database.

  • Op dit moment bestaat de database nog niet. Deze is echter wel nodig bij het werken met node-sqlite3.

Voeg vervolgens de volgende regels toe om een verbinding met de SQLite-database tot stand te brengen:

Hier,

  • De methode connectoToDatabase() brengt een verbinding met de database tot stand.

  • Binnen connectToDatabase(), roepen we de existsSync() methode van de fs-module aan binnen een if-statement. Het if-statement controleert het bestaan van de database op de opgegeven locatie.

    • Als de evaluatie van de voorwaarde true is, dan is de Database() klasse van de node-sqlite3 module. Zodra de verbinding tot stand is gebracht, retourneert de functie een object en eindigt deze.

    • Als de evaluatie van de voorwaarde false is (de database bestaat niet), dan springt de uitvoering naar het else-blok. Daar zal de Database() klasse worden geïnitieerd met twee argumenten: een pad naar het databasebestand en een callback.

In principe wordt de database aangemaakt als deze niet bestaat. Als er echter een fout optreedt tijdens het aanmaakproces, zal deze het error object instellen en de foutmelding afdrukken.

Vervolgens gaan we code introduceren om een tabel aan te maken als een database niet bestaat:

Hier,

  • De connectToDatabase() roept de createTable() functie aan die de objecten accepteert die zijn opgeslagen in db als een argument.

  • Buiten connectToDatabase(), hebben we de createTable() methode gedefinieerd die het verbindingsobject db als parameter accepteert.

  • De exec() methode op db neemt een SQL-statement als argument. Binnen dit SQL-statement hebben we de creatie van een tabel gedefinieerd migration met 7 kolommen, waarbij elke kolom overeenkomt met de kolomkoppen in het migration_data.csv bestand.

  • Ten slotte roepen we de connectToDatabase() methode en het exporteren van het verbindingsobject dat het retourneert, zodat we het in andere bestanden kunnen gebruiken.

Sla het bestand op en sluit de editor.

Vervolgens gaan we een ander programma maken om de geparste gegevens in de database in te voegen:

Voer de volgende code in in insert_data.js:

Hier,

  • We slaan het verbindingsobject verkregen uit csv-to-sqlite3.js op in de variabele db.

  • Binnen de data event callback (gekoppeld aan de fs module stream), roepen we de serialize() methode aan op het verbindingsobject. Dit zorgt ervoor dat de uitvoering van de ene SQL-instructie is voltooid voordat de volgende begint, wat database race conditions (systeem dat concurrerende bewerkingen tegelijkertijd uitvoert) voorkomt.

  • De serialize() accepteert drie argumenten:

    • Het eerste argument is de SQL-instructie.

    • Het tweede argument is een array.

    • Het derde argument is een callback die wordt uitgevoerd wanneer gegevens met succes of onsuccesvol in de database zijn ingevoegd.

We zijn klaar om het programma uit te voeren. Voer insert_data.js uit met behulp van Node.js:

Afhankelijk van de prestaties van het systeem kan het proces enige tijd duren om te voltooien. Na voltooiing zou de uitvoer er echter ongeveer zo uit moeten zien:

Stap 5 – Gegevens naar CSV schrijven

Na de laatste sectie hebben we een database met alle records die we hebben geparst uit migration_data.csv. In deze sectie gaan we de gegevens uit de database lezen en in een apart CSV-bestand schrijven.

Maak een nieuw JavaScript-bestand om het programma in op te slaan:

Voeg eerst de volgende regels toe om te importerenfs and csv-stringify  samen met het databaseverbindingsobject uit csv-to-sqlite3.js:

Vervolgens gaan we een variabele toevoegen die de naam van het CSV-bestand bevat waarnaar moet worden geschreven, samen met een writable stream:

Hier,

  • De createWriteStream()-methode accepteert de bestandsnaam waarnaar moet worden geschreven als argument. We gaan het bestand saved_from_db.csv.

  • De column-variabele slaat een array op die alle namen van de header voor de CSV-gegevens bevat.

Voeg vervolgens de volgende regels code toe om gegevens uit de database te lezen en deze te schrijven naar saved_from_db.csv:

Hier,

  • We roepen de stringify() methode aan met een object als argument. Dit resulteert in een transform stream die de gegevens van een object naar CSV-indeling converteert. Het object dat wordt doorgegeven aan stringify() heeft twee eigenschappen:

    • header: Accepteert een Boolean-waarde. Als de waarde true is, wordt er een header gegenereerd.

    • columns: Accepteert een array die de kolomnamen bevat die in de eerste regel van het CSV-bestand moeten worden geschreven als header is true.

  • De each() methode van het csv-to-sqlite3-verbindingsobject wordt aangeroepen met twee argumenten: de SQL-instructie (gegevens lezen uit de database) en een callback (afhandeling van succes/fout).

  • Bij elke iteratie van each(), pipe() (van de stringifier-stream) begint met het verzenden van gegevens in chunks naar de writable stream writableStream. Elk chunk met gegevens wordt vervolgens geschreven naar saved_from_db.csv.

  • Wanneer alle gegevens naar het CSV-bestand zijn geschreven, wordt er een succesbericht op het consolescherm afgedrukt.

De uiteindelijke code zou er als volgt uit moeten zien:

Sla het bestand op en sluit de editor. We kunnen het programma nu uitvoeren met Node.js:

Om te controleren of de gegevens succesvol zijn geëxporteerd, bekijk de inhoud van saved_from_db.csv:

Laatste overwegingen

In deze handleiding hebben we gedemonstreerd hoe u met CSV-bestanden werkt in Node.js met behulp van de modules node-csv en node-sqlite3. We hebben meerdere programma's gemaakt om verschillende taken uit te voeren, bijvoorbeeld het parseren van gegevens uit CSV, het pushen van de gegevens naar een SQLite-database en het schrijven van gegevens naar een nieuw CSV-bestand.

Deze handleiding toont slechts een klein deel van de mogelijkheden van de node-csv module. Lees meer over alle functies op CSV Project. Voor meer informatie over node-sqlite3, bekijk de officiële documentatie op GitHub. Een andere module die het vermelden waard is, is event-stream om het werken met streams te vereenvoudigen.

Geïnteresseerd in het verder uitbreiden van uw Node.js-project? Hier zijn enkele Node.js-handleidingen die u zou moeten bekijken:

Veel plezier met programmeren!

author

Preslav Dobrev

Auteur · CloudSigma

Preslav Dobrev is een creatief ontwerper bij CloudSigma, met de nadruk op een consistente bedrijfsidentiteit door middel van traditionele en innovatieve marketingkanalen. Hij is bedreven in het samenvoegen van artistieke visie met strategische marketing om impactvolle merkverhalen te creëren.

Reacties

Nog geen reacties. Wees de eerste.