返回部落格

在 Node.js 中使用 Node-CSV 管理 CSV

在 Node.js 中使用 Node-CSV 管理 CSV

一個 CSV 檔案是一個以表格格式儲存資料的純文字檔案。在大多數情況下,CSV 檔案使用逗號 (,) 作為分隔符,因此得名 CSV (逗號分隔值)。它’被用於需要考慮資料相容性的情況,因為 CSV 可以用任何文字編輯器、試算表應用程式和其他專業工具打開。事實上,許多程式語言都提供了對 CSV 的內建支援。

在本指南中,我們將學習如何在範例 Node.js 應用程式中使用 CSV。

在 Node.js 中使用 CSV

Node.js 是一個開源且跨平台的 JavaScript 執行環境。它已成為支援網際網路上眾多網路服務最受歡迎的後端之一。甚至像 Netflix 和 Uber 這樣的大公司也使用 Node.js 來支援他們的服務。

Node.js 也有許多模組可用於部署,以在專案中增加額外功能。說到 CSV,有許多模組可以使用,例如:node-csv, fast-csv、以及 papaparse 等。

正如指南標題所示,我們將使用 node-csv 來使用 Node.js 串流讀取 CSV 檔案。我們還將示範如何處理解析後的資料,例如將資料傳輸到 SQLite 資料庫中。

先決條件

步驟 1 – 安裝必要軟體

在本指南中,我建立了一個執行 Ubuntu 22.04 LTS 的輕量級伺服器(透過 SSH 連線):

現在,我們將在上面安裝 Node.js 和 SQLite。

  • 安裝 Node.js LTS

Node.js 可以直接從 Ubuntu 官方套件庫中取得。然而,它’並不是最新版本。這就是為什麼我們將依賴第三方套件庫(Nodesource)來獲取最新的 Node.js 套件。

新增 Node.js LTS 的套件庫:

現在,安裝 Node.js LTS:

  • 安裝 SQLite

我們將直接從 Ubuntu 套件庫安裝 SQLite。執行以下命令:

步驟 2 – 專案目錄設定

在本節中,我們將為專案準備一個專用目錄。它將存放所有專案檔案以及額外的模組。

建立一個新目錄:

進入該目錄:

接下來,執行以下命令將該目錄宣告為 npm 專案:

專案資料夾初始化完成後,我們就可以開始安裝必要的套件和模組。首先,我們將安裝 node-csv:

node-csv 模組實際上是其他幾個模組的集合:csv-generate, csv-parse(解析 CSV 檔案)、csv-stringify(將資料寫入 CSV)以及 stream-transform.

接下來,我們需要用於與 SQLite 通訊的模組。以下命令將安裝 node-sqlite3 模組:

我們專案所需的組件是一個 CSV 檔案。為了示範目的,我們將使用紐西蘭移民 CSV 檔案:

我們來快速查看一下檔案的內容:

這裡,

  • 第一行描述了欄位名稱。

  • 後續的行則包含這些欄位的值。

  • 每一行都由換行符號 (\n) 分隔。

  • 每個資料點都由逗號 (,) 分隔。

然而,CSV 並不限於使用逗號作為分隔符。其他常見的分隔符包括冒號 (:)、分號 (;) 和定位鍵 (\td)。

步驟 3 – 讀取 CSV

在本節中,我們將示範實作一個從 CSV 檔案讀取並解析資料的範例程式。

建立一個新的 JavaScript 檔案:

在您喜愛的文字編輯器中開啟該檔案:

首先,我們將匯入 fscsv-parse 模組:

這裡,

  • 首先, fs 變數被指派了 fs 物件,該物件在匯入模組時會傳回 Node.js 的 require() 方法。

  • 接下來,從 require() 方法傳回的物件中,使用 解構語法.

接下來,我們將加入讀取 CSV 檔案的程式碼:

這裡,

  • 我們正在呼叫 createReadStream() (來自 fs 模組),並將我們想要讀取的 CSV 檔案作為參數傳遞。然後,它透過將較大的檔案拆分為較小的區塊來建立一個可讀取串流(readable stream)。

  • 建立串流後, pipe() 方法會將串流資料的區塊轉發到另一個串流。這個新串流是在呼叫 parse() 方法(來自 csv-模組.

  • 這個 csv-模組 部署了一個可讀寫的轉換串流(transform stream),它接收資料區塊並將其轉換為另一種形式。

  • 這個 parse() 方法接受具有屬性的物件。該物件會進一步處理已解析的資料。在這裡,該物件具有以下屬性:

    • delimiter:用於分隔值的分隔字元。在我們的目標 CSV 中,它是逗號 (,)。

    • from_line:解析器開始解析的行數。給定值為 2 時,解析器將跳過第 1 行並從第 2 行開始。透過這種安排,我們可以避免將欄位名稱整合到解析後的資料中。

接下來,我們將使用 Node.js 的 on() 方法來附加一個串流事件:

這裡,

  • 在觸發特定事件時,串流事件允許方法取用資料區塊。

  • 當由 parse() 方法解析的資料準備好被取用時,它會觸發 data 事件。

  • 為了存取資料,我們向 on() 方法傳遞一個接受 row 參數的回呼函式。

  • row 參數是陣列形式的資料區塊(解析後的結果)。

  • 最後,使用 console.log().

將資料記錄在主控台中。為了完成程式,我們將加入額外的串流事件來處理錯誤,並在 CSV 檔案中的所有資料都被取用完畢時列印成功訊息。請如下更新程式碼:

這裡,

  • 當 CSV 檔案中的所有資料都被消耗完時,會觸發 end 事件。這會導致呼叫 console.log() 方法,該方法會列印成功訊息。

  • 在解析 CSV 資料時如果遇到錯誤,會觸發 error 事件。這會導致呼叫 console.log() 方法,該方法會列印錯誤訊息。

最終的程式碼應該像這樣:

儲存檔案並關閉編輯器。我們現在準備好執行程式了。使用 Node.js 執行它:

輸出應該看起來像這樣:

請注意,資料會被消耗、轉換並列印在主控台上。因為這是一個持續的過程,所以看起來會像是正在下載資料,而不是一次列印出所有輸出。

步驟 4 – 將 CSV 資料傳輸到資料庫

到目前為止,我們已經學習了如何使用 node-csv 解析 CSV 檔案。本節將示範如何將解析後的資料傳輸到資料庫 (SQLite) 中。

建立一個新的 JavaScript 檔案以與資料庫進行互動:

現在,在文字編輯器中開啟該檔案:

我們將使用以下程式碼開始我們的程式:

這裡,

  • 在第一行中,我們正在匯入 fs 模組。

  • 在第三行中,變數 filepath 包含 SQLite 資料庫的路徑。

  • 此時,資料庫還不存在。然而,當與 node-sqlite3.

搭配工作時,這將是必需的。接下來,加入以下幾行以建立與 SQLite 資料庫的連線:

在這裡,

  • 此方法 connectoToDatabase() 建立與資料庫的連接。

  • connectToDatabase() 中,我們正在呼叫 existsSync() 方法,該方法來自 if 語句中的 fs 模組。if 語句會檢查指定位置中是否存在該資料庫。

    • 如果條件評估為 true,那麼 Database() 類別,屬於 node-sqlite3 模組。一旦建立連接,該函式就會返回一個物件並結束。

    • 如果條件評估為 false (資料庫不存在),則執行將跳轉到 else 區塊。在該區塊中, Database() 類別將使用兩個引數進行初始化:資料庫檔案的路徑和一個回呼函式。

基本上,如果資料庫不存在,系統將會建立它。然而,如果在建立過程中發生任何錯誤,它將會設定 error 物件並列印錯誤訊息。

接下來,我們將引入程式碼,以便在資料庫不存在時建立資料表:

在這裡,

  • connectToDatabase() 呼叫了 createTable() 函式,該函式接受儲存在 db 中的物件作為引數。

  • connectToDatabase() 之外,我們定義了 createTable() 方法,該方法接受連接物件 db 作為參數。

  • exec() 方法(在 db 上)接受一個 SQL 語句作為引數。在此 SQL 語句中,我們定義了建立一個名為 migration 的資料表,其中包含 7 個欄位,每個欄位對應於 migration_data.csv 檔案中的欄位標題。

  • 最後,我們正在呼叫 connectToDatabase() 方法並匯出它傳回的連線物件,以便我們可以在其他檔案中使用它。

儲存檔案並關閉編輯器。

接下來,我們將建立另一個程式來將解析後的資料插入資料庫:

在 中輸入以下程式碼:insert_data.js:

在這裡,

  • 我們正在將從 csv-to-sqlite3.js 取得的連線物件儲存在變數 db.

  • 在 data 事件回呼(附加到 fs 模組串流)中,我們正在呼叫 serialize() 方法(在連線物件上)。它可確保一個 SQL 陳述式在下一個陳述式開始執行之前完成執行,從而防止資料庫競爭條件(系統同時執行競爭操作)。

  • serialize() 接受三個參數:

    • 第一個參數是 SQL 陳述式。

    • 第二個參數是一個陣列。

    • 第三個參數是一個回呼,當資料成功或失敗插入資料庫時會執行。

我們已準備好執行程式。請執行 insert_data.js(使用 Node.js):

根據系統’的效能,該程序可能需要一些時間才能完成。然而,完成後,輸出應該看起來像這樣:

步驟 5 – 將資料寫入 CSV

在上一節之後,我們得到了一個資料庫,其中包含我們從 migration_data.csv 解析的所有記錄。在本節中,我們將從資料庫中讀取資料並將其寫入一個獨立的 CSV 檔案中。

建立一個新的 JavaScript 檔案來儲存程式:

首先,加入以下幾行以匯入 fs 以及 csv-stringify ,以及來自 csv-to-sqlite3.js:

接下來,我們將添加一個變數,其中包含要寫入的 CSV 檔案名稱以及一個可寫入串流:

這裡,

  • createWriteStream() 方法將要寫入的檔案名稱作為參數。我們將該檔案命名為 saved_from_db.csv.

  • column 變數儲存了一個包含 CSV 資料所有標頭名稱的陣列。

接下來,添加以下幾行程式碼以從資料庫讀取資料並將其寫入 saved_from_db.csv:

這裡,

  • 我們正在呼叫 stringify() 方法,並將一個物件作為參數。這會產生一個轉換串流,將資料從物件格式轉換為 CSV 格式。傳遞給 stringify() 具有兩個屬性:

    • header:接受一個布林值。如果值為 true,則會生成標頭。

    • columns:接受一個包含欄位名稱的陣列,如果 headertrue.

  • each() 方法來自 csv-to-sqlite3 連線物件,並使用兩個參數進行呼叫:SQL 語句(從資料庫讀取資料)和回呼函式(處理成功/錯誤)。

  • 在每次迭代 each(), pipe()(來自 stringifier 串流)開始將資料分塊傳送到可寫入串流 writableStream。然後將每塊資料寫入 saved_from_db.csv.

  • 當所有資料都寫入 CSV 檔案時,主控台螢幕上會印出成功訊息。

最終的程式碼應該像這樣:

儲存檔案並關閉編輯器。我們現在可以使用 Node.js 執行該程式:

要確認資料是否已成功匯出,請檢查 saved_from_db.csv:

結語

在本指南中,我們示範了如何在 Node.js 中使用 node-csv 和 node-sqlite3 模組處理 CSV 檔案。我們建立了多個程式來完成各種任務,例如:解析 CSV 中的資料、將資料推送到 SQLite 資料庫,以及將資料寫入新的 CSV 檔案。

本指南僅展示了 node-csv 模組功能的一小部分。欲了解其所有功能的更多資訊,請參閱 CSV Project。欲了解更多關於 node-sqlite3 的資訊,請查看 GitHub 上的官方文件。另一個值得一提的模組是 event-stream,可用於簡化串流的操作。

有興趣進一步擴展您的 Node.js 專案嗎?以下是一些您應該參考的 Node.js 教學課程:

祝您開發愉快!

author

Preslav Dobrev

作者 · CloudSigma

Preslav Dobrev 是 CloudSigma 的創意設計師,專注於透過傳統與創新行銷渠道建立一致的企業形象。他擅長將藝術願景與策略行銷相融合,創造具有影響力的品牌敘事。

留言

目前尚無留言。成為第一個留言的人吧。