Powrót do bloga

Zarządzanie CSV w Node.js przy użyciu Node-CSV

Zarządzanie CSV w Node.js przy użyciu Node-CSV

Plik CSV to plik tekstowy, który przechowuje dane w formacie tabelarycznym. W większości przypadków pliki CSV używają przecinków (,) jako separatora, stąd nazwa CSV (Comma Separated Values). Jest on używany w sytuacjach, gdy kompatybilność danych ma znaczenie, ponieważ pliki CSV można otworzyć za pomocą dowolnego edytora tekstu, arkusza kalkulacyjnego i innych specjalistycznych narzędzi. W rzeczywistości wiele języków programowania oferuje wbudowane wsparcie dla CSV.

W tym poradniku dowiemy się, jak używać CSV w przykładowej aplikacji Node.js.

CSV w Node.js

Node.js to otwartoźródłowe i wieloplatformowe środowisko uruchomieniowe JavaScript. Stało się jednym z najpopularniejszych backendów zasilających liczne usługi internetowe w całym Internecie. Nawet duże firmy, takie jak Netflix i Uber, używają Node.js do zasilania swoich usług.

Node.js posiada również liczne moduły, które można wdrożyć w celu dodania dodatkowych funkcjonalności do projektu. Jeśli chodzi o CSV, dostępnych jest wiele modułów, na przykład node-csv, fast-csv, oraz papaparse itp.

Jak sugeruje tytuł poradnika, użyjemy node-csv do odczytu plików CSV przy użyciu strumieni Node.js. Zademonstrujemy również pracę ze sparsowanymi danymi, na przykład przenoszenie danych do bazy danych SQLite.

Wymagania wstępne

Krok 1 – Instalacja wymaganego oprogramowania

Na potrzeby tego poradnika utworzyłem lekki serwer z systemem Ubuntu 22.04 LTS (połączony przez SSH):

Teraz zainstalujemy na nim Node.js oraz SQLite.

  • Instalacja Node.js LTS

Node.js jest bezpośrednio dostępny w oficjalnych repozytoriach pakietów Ubuntu. Nie jest to jednak najnowsza wersja. Dlatego skorzystamy z zewnętrznego repozytorium (Nodesource) w celu pobrania najnowszych pakietów Node.js.

Dodaj repozytorium dla Node.js LTS:

Teraz zainstaluj Node.js LTS:

  • Instalacja SQLite

Zainstalujemy SQLite bezpośrednio z repozytoriów pakietów Ubuntu. Uruchom następujące polecenia:

Krok 2 – Konfiguracja katalogu projektu

W tej sekcji przygotujemy dedykowany katalog dla naszego projektu. Będzie on zawierał wszystkie pliki projektu wraz z dodatkowymi modułami.

Utwórz nowy katalog:

Przejdź do katalogu:

Następnie uruchom poniższe polecenie, aby zadeklarować katalog jako projekt npm :

Po zainicjowaniu folderu projektu możemy rozpocząć instalację niezbędnych pakietów i modułów. Najpierw zainstalujemy node-csv:

Moduł node-csv jest w rzeczywistości zbiorem kilku innych modułów: csv-generate, csv-parse (parsowanie plików CSV), csv-stringify (zapisywanie danych do CSV) oraz stream-transform.

Następnie potrzebujemy modułu do komunikacji z SQLite. Poniższe polecenie zainstaluje moduł node-sqlite3:

Komponentem, którego potrzebujemy do naszego projektu, jest plik CSV. Do celów demonstracyjnych użyjemy pliku CSV dotyczącego migracji w Nowej Zelandii:

Rzućmy szybko okiem na zawartość pliku:

Tutaj,

  • Pierwsza linia opisuje nazwy kolumn.

  • Kolejne linie zawierają wartości dla tych pól.

  • Każdy wiersz jest oddzielony nową linią (\n).

  • Każdy punkt danych jest oddzielony przecinkiem (,).

Jednak format CSV nie ogranicza się do używania przecinków jako separatora. Inne popularne separatory to dwukropki (:), średniki (;) i tabulatory (\td).

Krok 3 – Odczytywanie CSV

W tej sekcji zademonstrujemy implementację przykładowego programu, który odczytuje i analizuje dane z pliku CSV.

Utwórz nowy plik JavaScript:

Otwórz plik w swoim ulubionym edytorze tekstu:

Najpierw zaimportujemy moduły fs oraz csv-parse:

Tutaj,

  • Najpierw do zmiennej fs przypisywany jest obiekt fs, który zwraca metodę Node.js require() po zaimportowaniu modułu.

  • Następnie metoda parse jest wyodrębniana z obiektu zwróconego przez metodę require() do zmiennej parse przy użyciu składni destrukturyzacji.

Następnie dodamy kod do odczytu pliku CSV:

Tutaj,

  • Wywołujemy createReadStream() z modułu fs i przekazujemy jako argument plik CSV, który chcemy odczytać. Następnie tworzy on strumień do odczytu, dzieląc większy plik na mniejsze części.

  • Po utworzeniu strumienia metoda pipe() przekazuje części danych strumienia do innego strumienia. Ten nowy strumień jest tworzony po wywołaniu metody parse() z modułu csv-module.

  • Moduł csv-module wdraża strumień transformujący do odczytu/zapisu, który pobiera porcję danych i przekształca ją w inną formę.

  • Metoda parse() przyjmuje obiekty z właściwościami. Obiekt ten dalej przetwarza przeanalizowane dane. W tym przypadku obiekt przyjmuje następujące właściwości:

    • delimiter: Znak separatora służący do rozdzielania wartości. W przypadku naszego docelowego pliku CSV jest to przecinek (,).

    • from_line: Numer linii, od której parser rozpocznie analizę. Przy podanej wartości 2 parser pominie linię 1 i rozpocznie od linii 2. Dzięki temu unikamy włączenia nazw kolumn do przeanalizowanych danych.

Następnie dołączymy zdarzenie strumieniowe za pomocą metody on() z Node.js:

Tutaj,

  • Po wyemitowaniu określonego zdarzenia, zdarzenie strumieniowe pozwala metodzie na skonsumowanie porcji danych.

  • Gdy dane przeanalizowane przez metodę parse() są gotowe do skonsumowania, wyzwalane jest zdarzenie data.

  • Aby uzyskać dostęp do danych, przekazujemy funkcję wywołania zwrotnego do metody on(), która przyjmuje parametr row.

  • Parametr row to porcja danych w postaci tablicy (wynik analizy).

  • Na koniec dane są zapisywane w konsoli za pomocą console.log().

Aby zakończyć program, dodamy dodatkowe zdarzenia strumieniowe do obsługi błędów i wyświetlenia komunikatu o powodzeniu, gdy wszystkie dane z pliku CSV zostaną skonsumowane. Zaktualizuj kod w następujący sposób:

Tutaj,

  • Zdarzenie end jest emitowane, gdy wszystkie dane w pliku CSV zostaną skonsumowane. Powoduje to wywołanie metody console.log(), która wypisuje komunikat o sukcesie.

  • Zdarzenie error jest emitowane w przypadku napotkania błędu podczas parsowania danych CSV. Powoduje to wywołanie metody console.log() metody, która wypisuje komunikat o błędzie.

Ostateczny kod powinien wyglądać następująco:

Zapisz plik i zamknij edytor. Jesteśmy teraz gotowi do uruchomienia programu. Uruchom go za pomocą Node.js:

Dane wyjściowe powinny wyglądać mniej więcej tak:

Zauważ, że dane są konsumowane, transformowane i wypisywane w konsoli. Ponieważ jest to proces ciągły, będzie to wyglądać tak, jakby dane były pobierane, a nie wypisywane wszystkie naraz.

Krok 4 – Przenoszenie danych CSV do bazy danych

Do tej pory nauczyliśmy się, jak parsować plik CSV za pomocą node-csv. Ta sekcja zademonstruje przenoszenie sparsowanych danych do bazy danych (SQLite).

Utwórz nowy plik JavaScript do interakcji z bazą danych:

Teraz otwórz plik w edytorze tekstu:

Nasz program rozpoczniemy od następującego kodu:

Tutaj,

  • W pierwszej linii importujemy fs moduł.

  • W trzeciej linii zmienna filepath zawiera ścieżkę do bazy danych SQLite.

  • W tym momencie baza danych jeszcze nie istnieje. Będzie ona jednak niezbędna podczas pracy z node-sqlite3.

Następnie dodaj poniższe linie, aby nawiązać połączenie z bazą danych SQLite:

Tutaj,

  • Metoda connectoToDatabase() nawiązuje połączenie z bazą danych.

  • Wewnątrz connectToDatabase(), wywołujemy metodę existsSync() z modułu fs wewnątrz instrukcji warunkowej if. Instrukcja if sprawdza istnienie bazy danych w określonej lokalizacji.

    • Jeśli wynik warunku to true, wtedy klasa Database() modułu node-sqlite3 jest inicjowana. Po nawiązaniu połączenia funkcja zwraca obiekt i kończy działanie.

    • Jeśli wynik warunku to false (baza danych nie istnieje), wówczas wykonanie kodu przejdzie do bloku else. Tam klasa Database() zostanie zainicjowana z dwoma argumentami: ścieżką do pliku bazy danych oraz funkcją zwrotną (callback).

Zasadniczo baza danych zostanie utworzona, jeśli nie istnieje. Jeśli jednak podczas procesu tworzenia wystąpi jakikolwiek błąd, ustawi on obiekt error i wyświetli komunikat o błędzie.

Następnie wprowadzimy kod do utworzenia tabeli, jeśli baza danych nie istnieje:

Tutaj,

  • Funkcja connectToDatabase() wywołuje funkcję createTable() , która przyjmuje obiekt przechowywany w db jako argument.

  • Na zewnątrz connectToDatabase(), zdefiniowaliśmy funkcję createTable() , która przyjmuje obiekt połączenia db jako parametr.

  • Metoda exec() na obiekcie db przyjmuje instrukcję SQL jako argument. W ramach tej instrukcji SQL zdefiniowaliśmy utworzenie tabeli migration z 7 kolumnami, z których każda odpowiada nagłówkom kolumn w pliku migration_data.csv .

  • Na koniec wywołujemy connectToDatabase() metodę i eksportując zwracany przez nią obiekt połączenia, abyśmy mogli go użyć w innych plikach.

Zapisz plik i zamknij edytor.

Następnie utworzymy kolejny program, aby wstawić sparsowane dane do bazy danych:

Wprowadź następujący kod w insert_data.js:

Tutaj,

  • Przechowujemy obiekt połączenia uzyskany z csv-to-sqlite3.js w zmiennej db.

  • Wewnątrz wywołania zwrotnego zdarzenia data (dołączonego do strumienia modułu fs), wywołujemy serialize() metodę na obiekcie połączenia. Zapewnia ona, że jedna instrukcja SQL zakończy wykonywanie przed rozpoczęciem kolejnej, co zapobiega wyścigom w bazie danych (jednoczesnemu uruchamianiu konkurencyjnych operacji przez system).

  • Metoda serialize() przyjmuje trzy argumenty:

    • Pierwszym argumentem jest instrukcja SQL.

    • Drugim argumentem jest tablica.

    • Trzecim argumentem jest wywołanie zwrotne, które jest uruchamiane, gdy dane zostaną pomyślnie lub niepomyślnie wstawione do bazy danych.

Jesteśmy gotowi do uruchomienia programu. Uruchom insert_data.js za pomocą Node.js:

W zależności od wydajności systemu proces może zająć trochę czasu. Jednak po jego zakończeniu dane wyjściowe powinny wyglądać mniej więcej tak:

Krok 5 – Zapisywanie danych do pliku CSV

Po ostatniej sekcji mamy bazę danych zawierającą wszystkie rekordy, które sparsowaliśmy z migration_data.csv. W tej sekcji odczytamy dane z bazy danych i zapiszemy je w osobnym pliku CSV.

Utwórz nowy plik JavaScript, aby zapisać program:

Najpierw dodaj następujące linie, aby zaimportować fs oraz csv-stringify  wraz z obiektem połączenia z bazą danych z csv-to-sqlite3.js:

Następnie dodamy zmienną zawierającą nazwę pliku CSV, do którego będą zapisywane dane, wraz ze strumieniem zapisu:

Tutaj,

  • Metoda createWriteStream() przyjmuje jako argument nazwę pliku, do którego ma nastąpić zapis. Nazwiemy ten plik saved_from_db.csv.

  • Zmienna column przechowuje tablicę zawierającą wszystkie nazwy nagłówków dla danych CSV.

Następnie dodaj poniższe linie kodu, aby odczytać dane z bazy danych i zapisać je do saved_from_db.csv:

Tutaj,

  • Wywołujemy metodę stringify() z obiektem jako argumentem. Powoduje to powstanie strumienia transformującego (transform stream), który konwertuje dane z obiektu na format CSV. Obiekt przekazany do stringify() ma dwie właściwości:

    • header: Przyjmuje wartość logiczną (Boolean). Jeśli wartość wynosi true, generowany jest nagłówek.

    • columns: Przyjmuje tablicę zawierającą nazwy kolumn, które mają zostać zapisane w pierwszym wierszu pliku CSV, jeśli header wynosi true.

  • Metoda each() z obiektu połączenia csv-to-sqlite3 jest wywoływana z dwoma argumentami: instrukcją SQL (odczytującą dane z bazy danych) i funkcją wywołania zwrotnego (obsługującą sukces/błąd).

  • Przy każdej iteracji each(), pipe() (ze strumienia stringifier) zaczyna przesyłać dane partiami do strumienia zapisu writableStream. Każda partia danych jest następnie zapisywana do saved_from_db.csv.

  • Po zapisaniu wszystkich danych do pliku CSV na ekranie konsoli zostanie wyświetlony komunikat o sukcesie.

Ostateczny kod powinien wyglądać następująco:

Zapisz plik i zamknij edytor. Możemy teraz uruchomić program za pomocą Node.js:

Aby potwierdzić, czy dane zostały pomyślnie wyeksportowane, sprawdź zawartość saved_from_db.csv:

Podsumowanie

W tym poradniku zademonstrowaliśmy pracę z plikami CSV w Node.js przy użyciu modułów node-csv i node-sqlite3. Utworzyliśmy wiele programów do realizacji różnych zadań, na przykład analizowania danych z pliku CSV, wprowadzania danych do bazy danych SQLite oraz zapisywania danych do nowego pliku CSV.

Ten poradnik demonstruje tylko niewielką część możliwości node-csv modułu. Dowiedz się więcej o wszystkich jego funkcjach na stronie CSV Project. Aby dowiedzieć się więcej o node-sqlite3, zapoznaj się z oficjalną dokumentacją w serwisie GitHub. Innym modułem wartym wspomnienia jest event-stream ułatwiający pracę ze strumieniami.

Chcesz dalej rozwijać swój projekt Node.js? Oto kilka poradników dotyczących Node.js, z którymi warto się zapoznać:

Miłego kodowania!

author

Preslav Dobrev

Autor · CloudSigma

Preslav Dobrev jest projektantem kreatywnym w CloudSigma, skupiającym się na spójnej tożsamości biznesowej przy wykorzystaniu tradycyjnych i innowacyjnych kanałów marketingowych. Biegle łączy wizję artystyczną ze strategicznym marketingiem, tworząc wywierające wpływ narracje marki.

Komentarze

Brak komentarzy. Bądź pierwszy.