Wie man CSV-Dateien in Node.js mit Node-CSV liest und schreibt

Der Autor hat Society of Women Engineers ausgewählt, um eine Spende im Rahmen des Write for DOnations-Programms zu erhalten.

Einführung

A CSV is a plain text file format for storing tabular data. The CSV file uses a comma delimiter to separate values in table cells, and a new line delineates where rows begin and end. Most spreadsheet programs and databases can export and import CSV files. Because CSV is a plain-text file, any programming language can parse and write to a CSV file. Node.js has many modules that can work with CSV files, such as node-csv, fast-csv, and papaparse.

In diesem Tutorial verwenden Sie das Modul node-csv, um eine CSV-Datei mithilfe von Node.js-Streams zu lesen, was es Ihnen ermöglicht, große Datensätze zu lesen, ohne viel Speicher zu verbrauchen. Sie werden das Programm ändern, um Daten, die aus der CSV-Datei geparst wurden, in eine SQLite-Datenbank zu verschieben. Sie werden auch Daten aus der Datenbank abrufen, sie mit node-csv parsen und Node.js-Streams verwenden, um sie portionsweise in eine CSV-Datei zu schreiben.

Bereitstellen Sie Ihre Node-Anwendungen von GitHub aus mithilfe von DigitalOcean App Platform. Lassen Sie DigitalOcean Ihre App skalieren.

Voraussetzungen

Um diesem Tutorial zu folgen, benötigen Sie:

Schritt 1 – Einrichten des Projektverzeichnisses

In diesem Abschnitt erstellen Sie das Projektverzeichnis und laden Pakete für Ihre Anwendung herunter. Sie werden auch einen CSV-Datensatz von Stats NZ herunterladen, der Daten zur internationalen Migration in Neuseeland enthält.

Um loszulegen, erstellen Sie ein Verzeichnis namens csv_demo und navigieren Sie in das Verzeichnis:

  1. mkdir csv_demo
  2. cd csv_demo

Initialisieren Sie anschließend das Verzeichnis als ein npm-Projekt mit dem Befehl npm init:

  1. npm init -y

Die Option -y benachrichtigt npm init, um auf alle Aufforderungen mit „ja“ zu antworten. Dieser Befehl erstellt eine package.json-Datei mit Standardwerten, die Sie jederzeit ändern können.

Mit dem Verzeichnis als npm-Projekt initialisiert, können Sie nun die erforderlichen Abhängigkeiten installieren: node-csv und node-sqlite3.

Geben Sie den folgenden Befehl ein, um node-csv zu installieren:

  1. npm install csv

Das Modul node-csv ist eine Sammlung von Modulen, mit denen Sie Daten in einer CSV-Datei analysieren und schreiben können. Der Befehl installiert alle vier Module, die Teil des node-csv-Pakets sind: csv-generate, csv-parse, csv-stringify und stream-transform. Sie werden das Modul csv-parse verwenden, um eine CSV-Datei zu analysieren, und das Modul csv-stringify, um Daten in eine CSV-Datei zu schreiben.

Anschließend installieren Sie das Modul node-sqlite3:

  1. npm install sqlite3

Das Modul node-sqlite3 ermöglicht es Ihrer App, mit der SQLite-Datenbank zu interagieren.

Nachdem Sie die Pakete in Ihrem Projekt installiert haben, laden Sie die CSV-Datei zur Migration nach Neuseeland mit dem wget-Befehl herunter:

  1. wget https://www.stats.govt.nz/assets/Uploads/International-migration/International-migration-September-2021-Infoshare-tables/Download-data/international-migration-September-2021-estimated-migration-by-age-and-sex-csv.csv

Die heruntergeladene CSV-Datei hat einen langen Namen. Um die Arbeit damit zu vereinfachen, benennen Sie den Dateinamen mit dem mv-Befehl um:

  1. mv international-migration-September-2021-estimated-migration-by-age-and-sex-csv.csv migration_data.csv

Der neue CSV-Dateiname, migration_data.csv, ist kürzer und einfacher zu handhaben.

Öffnen Sie die Datei mit nano oder Ihrem bevorzugten Texteditor:

  1. nano migration_data.csv

Einmal geöffnet, sehen Sie Inhalte, die ähnlich wie folgt aussehen:

demo_csv/migration_data.csv
year_month,month_of_release,passenger_type,direction,sex,age,estimate,standard_error,status
2001-01,2020-09,Long-term migrant,Arrivals,Female,0-4 years,344,0,Final
2001-01,2020-09,Long-term migrant,Arrivals,Male,0-4 years,341,0,Final
...

Die erste Zeile enthält die Spaltennamen, und alle nachfolgenden Zeilen enthalten die Daten, die jeder Spalte entsprechen. Ein Komma trennt jedes Datenstück. Dieses Zeichen wird als Trennzeichen bezeichnet, da es die Felder abgrenzt. Sie sind nicht auf die Verwendung von Kommas beschränkt. Andere beliebte Trennzeichen sind Doppelpunkte (:), Semikolons (;) und Tabs (\t). Sie müssen wissen, welches Trennzeichen in der Datei verwendet wird, da die meisten Module es zum Analysieren der Dateien benötigen.

Nachdem Sie die Datei überprüft und das Trennzeichen identifiziert haben, beenden Sie Ihre migration_data.csv-Datei mit CTRL+X.

Sie haben nun die erforderlichen Abhängigkeiten für Ihr Projekt installiert. Im nächsten Abschnitt werden Sie eine CSV-Datei einlesen.

Schritt 2 — Lesen von CSV-Dateien

In diesem Abschnitt werden Sie node-csv verwenden, um eine CSV-Datei zu lesen und ihren Inhalt in der Konsole auszugeben. Sie werden die Methode createReadStream() des Moduls fs verwenden, um die Daten aus der CSV-Datei zu lesen und einen lesbaren Stream zu erstellen. Anschließend leiten Sie den Stream an einen anderen Stream weiter, der mit dem Modul csv-parse initialisiert wurde, um die Datenstücke zu analysieren. Sobald die Datenstücke analysiert wurden, können Sie sie in der Konsole ausgeben.

Erstellen Sie eine readCSV.js-Datei in Ihrem bevorzugten Editor:

  1. nano readCSV.js

In Ihrer readCSV.js-Datei importieren Sie die Module fs und csv-parse, indem Sie die folgenden Zeilen hinzufügen:

demo_csv/readCSV.js
const fs = require("fs");
const { parse } = require("csv-parse");

In der ersten Zeile definieren Sie die Variable fs und weisen ihr das fs-Objekt zu, das die Node.js require()-Methode zurückgibt, wenn das Modul importiert wird.

In der zweiten Zeile extrahieren Sie die parse-Methode aus dem Objekt, das von der require()-Methode zurückgegeben wird, in die Variable parse mithilfe der Destrukturierungssyntax.

Fügen Sie die folgenden Zeilen hinzu, um die CSV-Datei zu lesen:

demo_csv/readCSV.js
...
fs.createReadStream("./migration_data.csv")
  .pipe(parse({ delimiter: ",", from_line: 2 }))
  .on("data", function (row) {
    console.log(row);
  })

Die Methode createReadStream() des Moduls fs akzeptiert ein Argument mit dem Dateinamen, den Sie lesen möchten, der hier migration_data.csv ist. Dann erstellt es einen lesbaren Stream, der eine große Datei nimmt und sie in kleinere Teile aufteilt. Ein lesbbarer Stream ermöglicht es Ihnen nur, Daten daraus zu lesen und nicht zu schreiben.

Nachdem der lesbare Stream erstellt wurde, leitet die pipe()-Methode von Node Datenblöcke vom lesbaren Stream an einen anderen Stream weiter. Der zweite Stream wird erstellt, wenn die parse()-Methode des Moduls csv-parse innerhalb der pipe()-Methode aufgerufen wird. Das Modul csv-parse implementiert einen Transformations-Stream (einen lesbaren und schreibbaren Stream), der einen Datenblock nimmt und ihn in eine andere Form transformiert. Wenn es beispielsweise einen Block wie 2001-01,2020-09,Langzeitmigrant,Ankünfte,Weiblich,0-4 Jahre,344 erhält, wird die parse()-Methode ihn in ein Array transformieren.

Die parse()-Methode akzeptiert ein Objekt, das Eigenschaften akzeptiert. Das Objekt konfiguriert und liefert dann weitere Informationen über die Daten, die die Methode parsen wird. Das Objekt nimmt die folgenden Eigenschaften an:

  • delimiter definiert das Zeichen, das jedes Feld in der Zeile trennt. Der Wert , teilt dem Parser mit, dass Kommas die Felder abgrenzen.

  • from_line definiert die Zeile, ab der der Parser mit dem Parsen der Zeilen beginnen soll. Mit dem Wert 2 überspringt der Parser Zeile 1 und beginnt mit Zeile 2. Da Sie die Daten später in die Datenbank einfügen, hilft Ihnen diese Eigenschaft dabei, die Spaltennamen nicht in der ersten Zeile der Datenbank einzufügen.

Anschließend hängen Sie ein Streaming-Ereignis unter Verwendung der Node.js-Methode on() an. Ein Streaming-Ereignis ermöglicht es der Methode, einen Datenchunk zu konsumieren, wenn ein bestimmtes Ereignis ausgelöst wird. Das data-Ereignis wird ausgelöst, wenn Daten, die aus der parse()-Methode transformiert wurden, bereit sind, konsumiert zu werden. Um auf die Daten zuzugreifen, übergeben Sie der on()-Methode eine Callback-Funktion, die einen Parameter namens row annimmt. Der row-Parameter ist ein Datenchunk, der in ein Array transformiert wurde. Innerhalb der Callback-Funktion protokollieren Sie die Daten in der Konsole mit der Methode console.log().

Vor dem Ausführen der Datei fügen Sie weitere Stream-Ereignisse hinzu. Diese Stream-Ereignisse behandeln Fehler und schreiben eine Erfolgsmeldung in die Konsole, wenn alle Daten in der CSV-Datei verbraucht wurden.

Weiterhin in Ihrer readCSV.js-Datei fügen Sie den hervorgehobenen Code hinzu:

demo_csv/readCSV.js
...
fs.createReadStream("./migration_data.csv")
  .pipe(parse({ delimiter: ",", from_line: 2 }))
  .on("data", function (row) {
    console.log(row);
  })
  .on("end", function () {
    console.log("finished");
  })
  .on("error", function (error) {
    console.log(error.message);
  });

Das end-Ereignis wird ausgelöst, wenn alle Daten in der CSV-Datei gelesen wurden. Wenn dies geschieht, wird der Rückruf aufgerufen und protokolliert eine Nachricht, die besagt, dass er beendet wurde.

Wenn irgendwo beim Lesen und Parsen der CSV-Daten ein Fehler auftritt, wird das error-Ereignis ausgelöst, das den Rückruf aufruft und die Fehlermeldung in der Konsole protokolliert.

Ihre vollständige Datei sollte jetzt wie folgt aussehen:

demo_csv/readCSV.js
const fs = require("fs");
const { parse } = require("csv-parse");

fs.createReadStream("./migration_data.csv")
  .pipe(parse({ delimiter: ",", from_line: 2 }))
  .on("data", function (row) {
    console.log(row);
  })
  .on("end", function () {
    console.log("finished");
  })
  .on("error", function (error) {
    console.log(error.message);
  });

Speichern und verlassen Sie Ihre readCSV.js-Datei mit CTRL+X.

Führen Sie anschließend die Datei mit dem Befehl node aus:

  1. node readCSV.js

Die Ausgabe wird ähnlich aussehen wie folgt (zur Kürze bearbeitet):

Output
[ '2001-01', '2020-09', 'Long-term migrant', 'Arrivals', 'Female', '0-4 years', '344', '0', 'Final' ] ... [ '2021-09', ... '70', 'Provisional' ] finished

Alle Zeilen in der CSV-Datei wurden mithilfe des csv-parse-Transformstreams in Arrays umgewandelt. Da das Protokollieren jedes Mal erfolgt, wenn ein Chunk vom Stream empfangen wird, erscheinen die Daten so, als würden sie heruntergeladen, anstatt alle auf einmal angezeigt zu werden.

In diesem Schritt lesen Sie Daten in einer CSV-Datei und wandeln sie in Arrays um. Als nächstes werden Sie Daten aus einer CSV-Datei in die Datenbank einfügen.

Schritt 3 — Daten in die Datenbank einfügen

Das Einfügen von Daten aus einer CSV-Datei in die Datenbank mit Node.js gibt Ihnen Zugriff auf eine umfangreiche Bibliothek von Modulen, die Sie zur Verarbeitung, Bereinigung oder Verbesserung der Daten vor dem Einfügen in die Datenbank verwenden können.

In diesem Abschnitt stellen Sie eine Verbindung mit der SQLite-Datenbank unter Verwendung des Moduls node-sqlite3 her. Anschließend erstellen Sie eine Tabelle in der Datenbank, kopieren die Datei readCSV.js und ändern sie, um alle Daten aus der CSV-Datei in die Datenbank einzufügen.

Erstellen Sie eine db.js-Datei in Ihrem Editor:

  1. nano db.js

Fügen Sie in Ihrer db.js-Datei die folgenden Zeilen hinzu, um die Module fs und node-sqlite3 zu importieren:

demo_csv/db.js
const fs = require("fs");
const sqlite3 = require("sqlite3").verbose();
const filepath = "./population.db";
...

In der dritten Zeile definieren Sie den Pfad der SQLite-Datenbank und speichern ihn in der Variablen filepath. Die Datenbankdatei existiert noch nicht, wird aber für node-sqlite3 benötigt, um eine Verbindung mit der Datenbank herzustellen.

Fügen Sie in derselben Datei die folgenden Zeilen hinzu, um Node.js mit einer SQLite-Datenbank zu verbinden:

demo_csv/db.js
...
function connectToDatabase() {
  if (fs.existsSync(filepath)) {
    return new sqlite3.Database(filepath);
  } else {
    const db = new sqlite3.Database(filepath, (error) => {
      if (error) {
        return console.error(error.message);
      }
      console.log("Connected to the database successfully");
    });
    return db;
  }
}

Hier definieren Sie eine Funktion namens connectToDatabase(), um eine Verbindung zur Datenbank herzustellen. Innerhalb der Funktion rufen Sie die Methode existsSync() des Moduls fs in einer if-Anweisung auf, die überprüft, ob die Datenbankdatei im Projektverzeichnis vorhanden ist. Wenn die Bedingung des if zutrifft, instanziieren Sie die Klasse Database() von SQLite des Moduls node-sqlite3 mit dem Dateipfad der Datenbank. Sobald die Verbindung hergestellt ist, gibt die Funktion das Verbindungsobjekt zurück und beendet sich.

Wenn jedoch die if-Anweisung zu false ausgewertet wird (wenn die Datenbankdatei nicht vorhanden ist), wird die Ausführung zum else-Block überspringen. Im else-Block instanziieren Sie die Klasse Database() mit zwei Argumenten: dem Dateipfad der Datenbank und einem Rückruf.

Das erste Argument ist der Pfad der SQLite-Datenbankdatei, der ./population.db ist. Das zweite Argument ist ein Rückruf, der automatisch aufgerufen wird, wenn die Verbindung mit der Datenbank erfolgreich hergestellt wurde oder wenn ein Fehler aufgetreten ist. Der Rückruf nimmt ein error-Objekt als Parameter, das null ist, wenn die Verbindung erfolgreich ist. Innerhalb des Rückrufs überprüft die if-Anweisung, ob das error-Objekt gesetzt ist. Wenn es zu true ausgewertet wird, protokolliert der Rückruf eine Fehlermeldung und gibt zurück. Wenn es zu false ausgewertet wird, protokollieren Sie eine Erfolgsmeldung, die bestätigt, dass die Verbindung hergestellt wurde.

Aktuell erstellen die if und else Blöcke das Verbindungsobjekt. Sie übergeben eine Rückruffunktion, wenn Sie die Database-Klasse im else Block aufrufen, um eine Tabelle in der Datenbank zu erstellen, aber nur wenn die Datenbankdatei nicht existiert. Wenn die Datenbankdatei bereits vorhanden ist, wird die Funktion den if Block ausführen, sich mit der Datenbank verbinden und das Verbindungsobjekt zurückgeben.

Um eine Tabelle zu erstellen, wenn die Datenbankdatei nicht existiert, fügen Sie den markierten Code hinzu:

demo_csv/db.js
const fs = require("fs");
const sqlite3 = require("sqlite3").verbose();
const filepath = "./population.db";

function connectToDatabase() {
  if (fs.existsSync(filepath)) {
    return new sqlite3.Database(filepath);
  } else {
    const db = new sqlite3.Database(filepath, (error) => {
      if (error) {
        return console.error(error.message);
      }
      createTable(db);
      console.log("Connected to the database successfully");
    });
    return db;
  }
}

function createTable(db) {
  db.exec(`
  CREATE TABLE migration
  (
    year_month       VARCHAR(10),
    month_of_release VARCHAR(10),
    passenger_type   VARCHAR(50),
    direction        VARCHAR(20),
    sex              VARCHAR(10),
    age              VARCHAR(50),
    estimate         INT
  )
`);
}

module.exports = connectToDatabase();

Jetzt ruft connectToDatabase() die Funktion createTable() auf, die das Verbindungsobjekt, das in der Variablen db gespeichert ist, als Argument akzeptiert.

Außerhalb der Funktion connectToDatabase() definieren Sie die Funktion createTable(), die das Verbindungsobjekt db als Parameter akzeptiert. Sie rufen die Methode exec() auf dem db Verbindungsobjekt auf, die einen SQL-Befehl als Argument erhält. Der SQL-Befehl erstellt eine Tabelle mit dem Namen migration mit 7 Spalten. Die Spaltennamen entsprechen den Überschriften in der Datei migration_data.csv.

Zuletzt rufen Sie die Funktion connectToDatabase() auf und exportieren das zurückgegebene Verbindungsobjekt, damit es in anderen Dateien wiederverwendet werden kann.

Speichern und beenden Sie Ihre db.js Datei.

Mit der hergestellten Datenbankverbindung werden Sie nun die Datei readCSV.js kopieren und ändern, um die Zeilen, die das Modul csv-parse analysiert hat, in die Datenbank einzufügen.

Kopieren Sie die Datei und benennen Sie sie mit dem folgenden Befehl in insertData.js um:

  1. cp readCSV.js insertData.js

Öffnen Sie die Datei insertData.js in Ihrem Editor:

  1. nano insertData.js

Fügen Sie den hervorgehobenen Code hinzu:

demo_csv/insertData.js
const fs = require("fs");
const { parse } = require("csv-parse");
const db = require("./db");

fs.createReadStream("./migration_data.csv")
  .pipe(parse({ delimiter: ",", from_line: 2 }))
  .on("data", function (row) {
    db.serialize(function () {
      db.run(
        `INSERT INTO migration VALUES (?, ?, ? , ?, ?, ?, ?)`,
        [row[0], row[1], row[2], row[3], row[4], row[5], row[6]],
        function (error) {
          if (error) {
            return console.log(error.message);
          }
          console.log(`Inserted a row with the id: ${this.lastID}`);
        }
      );
    });
  });

In der dritten Zeile importieren Sie das Verbindungsobjekt aus der Datei db.js und speichern es in der Variable db.

Innerhalb des data-Ereignisrückrufs, der an den fs-Modulstream angehängt ist, rufen Sie die Methode serialize() auf dem Verbindungsobjekt auf. Die Methode stellt sicher, dass eine SQL-Anweisung ausgeführt wird, bevor eine andere ausgeführt wird, was dazu beitragen kann, Datenbank-Rennbedingungen zu verhindern, bei denen das System gleichzeitig konkurrierende Operationen ausführt.

Die Methode serialize() nimmt eine Rückruffunktion entgegen. Innerhalb des Rückrufs rufen Sie die Methode run auf dem db-Verbindungsobjekt auf. Die Methode akzeptiert drei Argumente:

  • Das erste Argument ist eine SQL-Anweisung, die an die SQLite-Datenbank übergeben und ausgeführt wird. Die Methode run() akzeptiert nur SQL-Anweisungen, die keine Ergebnisse zurückgeben. Die Anweisung INSERT INTO migration VALUES (?, ..., ?) fügt eine Zeile in die Tabelle migration ein, und die ? sind Platzhalter, die später durch die Werte im zweiten Argument der Methode run() ersetzt werden.

  • Das zweite Argument ist ein Array [row[0], ... row[5], row[6]]. Im vorherigen Abschnitt empfängt die Methode parse() einen Datenblock aus dem lesbaren Stream und wandelt ihn in ein Array um. Da die Daten als Array empfangen werden, müssen Sie für den Zugriff auf jeden Feldwert Array-Indizes verwenden, wie [row[1], ..., row[6]] usw.

  • Das dritte Argument ist ein Rückruf, der ausgeführt wird, wenn die Daten eingefügt wurden oder ein Fehler aufgetreten ist. Der Rückruf überprüft, ob ein Fehler aufgetreten ist, und protokolliert die Fehlermeldung. Wenn keine Fehler vorliegen, protokolliert die Funktion eine Erfolgsmeldung in der Konsole mithilfe der Methode console.log(), um Sie darüber zu informieren, dass eine Zeile eingefügt wurde, zusammen mit der ID.

Entfernen Sie schließlich die Ereignisse end und error aus Ihrer Datei. Aufgrund der asynchronen Natur der Methoden von node-sqlite3 werden die Ereignisse end und error ausgeführt, bevor die Daten in die Datenbank eingefügt werden, daher sind sie nicht mehr erforderlich.

Speichern Sie Ihre Datei und beenden Sie sie.

Führen Sie die Datei insertData.js mit node aus:

  1. node insertData.js

Je nach Ihrem System kann es einige Zeit dauern, aber node sollte die folgende Ausgabe zurückgeben:

Output
Connected to the database successfully Inserted a row with the id: 1 Inserted a row with the id: 2 ... Inserted a row with the id: 44308 Inserted a row with the id: 44309 Inserted a row with the id: 44310

Die Nachricht, insbesondere die IDs, beweist, dass die Zeile aus der CSV-Datei in die Datenbank gespeichert wurde.

Sie können jetzt eine CSV-Datei lesen und ihren Inhalt in die Datenbank einfügen. Als nächstes werden Sie eine CSV-Datei schreiben.

Schritt 4 — Schreiben von CSV-Dateien

In diesem Abschnitt werden Daten aus der Datenbank abgerufen und in eine CSV-Datei mit Streams geschrieben.

Erstellen und öffnen Sie writeCSV.js in Ihrem Editor:

  1. nano writeCSV.js

Fügen Sie Ihrer Datei writeCSV.js die folgenden Zeilen hinzu, um die Module fs und csv-stringify sowie das Verbindungsobjekt zur Datenbank aus db.js zu importieren:

demo_csv/writeCSV.js
const fs = require("fs");
const { stringify } = require("csv-stringify");
const db = require("./db");

Das Modul csv-stringify wandelt Daten aus einem Objekt oder Array in ein CSV-Textformat um.

Als Nächstes fügen Sie die folgenden Zeilen hinzu, um eine Variable zu definieren, die den Namen der CSV-Datei enthält, in die Sie Daten schreiben möchten, und einen beschreibbaren Stream, in den Sie Daten schreiben werden:

demo_csv/writeCSV.js
...
const filename = "saved_from_db.csv";
const writableStream = fs.createWriteStream(filename);

const columns = [
  "year_month",
  "month_of_release",
  "passenger_type",
  "direction",
  "sex",
  "age",
  "estimate",
];

Die Methode createWriteStream erwartet ein Argument mit dem Dateinamen, in die Sie Ihren Datenstrom schreiben möchten, der der Dateiname saved_from_db.csv ist, der in der Variablen filename gespeichert ist.

In der vierten Zeile definieren Sie eine Variable columns, die ein Array speichert, das die Namen der Header für die CSV-Daten enthält. Diese Header werden in der ersten Zeile der CSV-Datei geschrieben, wenn Sie die Daten in die Datei schreiben.

Weiterhin in Ihrer Datei writeCSV.js fügen Sie die folgenden Zeilen hinzu, um Daten aus der Datenbank abzurufen und jede Zeile in der CSV-Datei zu schreiben:

demo_csv/writeCSV.js
...
const stringifier = stringify({ header: true, columns: columns });
db.each(`select * from migration`, (error, row) => {
  if (error) {
    return console.log(error.message);
  }
  stringifier.write(row);
});
stringifier.pipe(writableStream);
console.log("Finished writing data");

Zuerst rufen Sie die Methode stringify mit einem Objekt als Argument auf, das einen Transformationsstrom erzeugt. Der Transformationsstrom wandelt die Daten von einem Objekt in CSV-Text um. Das Objekt, das der Methode stringify() übergeben wird, hat zwei Eigenschaften:

  • header akzeptiert einen booleschen Wert und generiert einen Header, wenn der boolesche Wert auf true gesetzt ist.
  • columns nimmt ein Array entgegen, das die Namen der Spalten enthält, die in der ersten Zeile der CSV-Datei geschrieben werden, wenn die Option header auf true gesetzt ist.

Als nächstes rufen Sie die each()-Methode des db-Verbindungsobjekts mit zwei Argumenten auf. Das erste Argument ist die SQL-Anweisung select * from migration, die die Zeilen nacheinander aus der Datenbank abruft. Das zweite Argument ist eine Rückruffunktion, die jedes Mal aufgerufen wird, wenn eine Zeile aus der Datenbank abgerufen wird. Der Rückruf nimmt zwei Parameter entgegen: ein error-Objekt und ein row-Objekt, das die aus einer einzelnen Zeile in der Datenbank abgerufenen Daten enthält. Innerhalb des Rückrufs prüfen Sie, ob das error-Objekt im if-Statement gesetzt ist. Wenn die Bedingung als true ausgewertet wird, wird eine Fehlermeldung mit der console.log()-Methode in der Konsole protokolliert. Wenn kein Fehler vorliegt, rufen Sie die write()-Methode auf stringifier auf, die die Daten in den stringifier-Transformationsstrom schreibt.

Wenn die each()-Methode mit der Iteration fertig ist, beginnt die pipe()-Methode auf dem stringifier-Strom, Daten in Teilen zu senden und sie in den writableStream zu schreiben. Der beschreibbare Strom speichert jedes Datenfragment in der Datei saved_from_db.csv. Sobald alle Daten in die Datei geschrieben wurden, gibt console.log() eine Erfolgsmeldung aus.

Die vollständige Datei sieht jetzt wie folgt aus:

demo_csv/writeCSV.js
const fs = require("fs");
const { stringify } = require("csv-stringify");
const db = require("./db");
const filename = "saved_from_db.csv";
const writableStream = fs.createWriteStream(filename);

const columns = [
  "year_month",
  "month_of_release",
  "passenger_type",
  "direction",
  "sex",
  "age",
  "estimate",
];

const stringifier = stringify({ header: true, columns: columns });
db.each(`select * from migration`, (error, row) => {
  if (error) {
    return console.log(error.message);
  }
  stringifier.write(row);
});
stringifier.pipe(writableStream);
console.log("Finished writing data");

Speichern und schließen Sie Ihre Datei, und führen Sie dann die Datei writeCSV.js im Terminal aus:

  1. node writeCSV.js

Sie erhalten die folgende Ausgabe:

Output
Finished writing data

Um zu bestätigen, dass die Daten geschrieben wurden, überprüfen Sie den Inhalt der Datei mithilfe des cat-Befehls:

  1. cat saved_from_db.csv

cat gibt alle Zeilen aus der Datei zurück (bearbeitet für Kürze):

Output
year_month,month_of_release,passenger_type,direction,sex,age,estimate 2001-01,2020-09,Long-term migrant,Arrivals,Female,0-4 years,344 2001-01,2020-09,Long-term migrant,Arrivals,Male,0-4 years,341 2001-01,2020-09,Long-term migrant,Arrivals,Female,10-14 years, ...

Sie können nun Daten aus der Datenbank abrufen und jede Zeile in einer CSV-Datei mithilfe von Streams schreiben.

Abschluss

In diesem Artikel haben Sie eine CSV-Datei gelesen und ihre Daten mithilfe der Module node-csv und node-sqlite3 in eine Datenbank eingefügt. Anschließend haben Sie Daten aus der Datenbank abgerufen und in eine andere CSV-Datei geschrieben.

Sie können jetzt CSV-Dateien lesen und schreiben. Als nächster Schritt können Sie nun mit großen CSV-Datensätzen arbeiten, indem Sie dieselbe Implementierung mit speichereffizienten Streams verwenden, oder Sie könnten sich ein Paket wie event-stream ansehen, das die Arbeit mit Streams wesentlich erleichtert.

Um mehr über node-csv zu erfahren, besuchen Sie deren Dokumentation CSV-Projekt – Node.js CSV-Paket. Um mehr über node-sqlite3 zu erfahren, besuchen Sie deren Github-Dokumentation. Um Ihre Node.js-Kenntnisse weiter auszubauen, sehen Sie sich die Anleitung zum Programmieren in Node.js-Serie an.

Source:
https://www.digitalocean.com/community/tutorials/how-to-read-and-write-csv-files-in-node-js-using-node-csv