簡體   English   中英

將 csv-parse 輸出保存到變量

[英]Save csv-parse output to a variable

我是使用 csv-parse 的新手,這個來自項目 github 的示例滿足了我的需求,但有一個例外。 我想將數據存儲在變量中,而不是通過 console.log 輸出。 我試過將 fs 行分配給一個變量,然后返回data而不是記錄它,但這只是返回了一大堆我不明白的東西。 最終目標是將 CSV 文件導入 SQLite。

var fs = require('fs');
var parse = require('..');

var parser = parse({delimiter: ';'}, function(err, data){
  console.log(data);
});

fs.createReadStream(__dirname+'/fs_read.csv').pipe(parser);

這是我嘗試過的:

const fs = require("fs");
const parse = require("./node_modules/csv-parse");

const sqlite3 = require("sqlite3");
// const db = new sqlite3.Database("testing.sqlite");

let parser = parse({delimiter: ","}, (err, data) => {
    // console.log(data);
    return data;
});

const output = fs.createReadStream(__dirname + "/users.csv").pipe(parser);
console.log(output);

我也在努力弄清楚如何將數據從 csv-parse 返回到調用解析的頂層。 具體來說,我試圖在處理結束時獲取 parser.info 數據以查看它是否成功,但是如果需要,該解決方案也可以用於獲取行數據。

關鍵是將所有流事件偵聽器包裝到一個 Promise 中,並在解析器的回調中解析 Promise。

function startFileImport(myFile) {

  // THIS IS THE WRAPPER YOU NEED
  return new Promise((resolve, reject) => {

    let readStream = fs.createReadStream(myFile);

    let fileRows = [];
    const parser = parse({
      delimiter: ','
    });

    // Use the readable stream api
    parser.on('readable', function () {
      let record
      while (record = parser.read()) {
        if (record) { fileRows.push(record); }
      }
    });

    // Catch any error
    parser.on('error', function (err) {
      console.error(err.message)
    });

    parser.on('end', function () {
      const { lines } = parser.info;
      // RESOLVE OUTPUT THAT YOU WANT AT PARENT-LEVEL
      resolve({ status: 'Successfully processed lines: ', lines });
    });

    // This will wait until we know the readable stream is actually valid before piping                
    readStream.on('open', function () {
      // This just pipes the read stream to the response object (which goes to the client)
      readStream.pipe(parser);
    });

    // This catches any errors that happen while creating the readable stream (usually invalid names)
    readStream.on('error', function (err) {
      resolve({ status: null, error: 'readStream error' + err });
    });

  });
}

這是一個讓人對異步流API感到困惑的問題,似乎至少要問三件事。

  1. 如何獲得包含表示已解析的CSV數據的數組的output

就像您(和許多其他程序員)希望的那樣,由於異步API的運行方式,該output將永遠不會像您(和其他許多程序員)所希望的那樣存在於頂層。 整齊地組裝在一個地方的所有數據只能存在於回調函數中。 從語法const output = await somePromiseOfOutput() ,下一個最好的事情是const output = await somePromiseOfOutput()但這只能在async function發生,並且僅當我們從流切換到const output = await somePromiseOfOutput()時才發生。 這都是可能的,我提到了它,因此您以后可以自己檢查出來。 我假設您要堅持使用流。

由所有行組成的數組只能在讀取整個流之后存在。 這就是為什么所有行僅在作者的“ Stream API”示例中僅在.on('end', ...)回調中可用的原因。 如果您想同時處理所有存在的行,則需要在end回調中進行。

https://csv.js.org/parse/api/注意到作者:

  1. 使用on可讀回調將單個記錄推入一個外部命名為output空數組。
  2. 使用on error回調報告錯誤
  3. 使用on end回調將輸出中的所有累積記錄與預期結果進行比較

... const output = [] ... parser.on('readable', function(){ let record while (record = parser.read()) { output.push(record) } }) // Catch any error parser.on('error', function(err){ console.error(err.message) }) // When we are done, test that the parsed output matched what expected parser.on('end', function(){ assert.deepEqual( output, [ [ 'root','x','0','0','root','/root','/bin/bash' ], [ 'someone','x','1022','1022','','/home/someone','/bin/bash' ] ] ) })

  1. 至於與sqlite接口的目標,這實際上是在構建自定義的流終結點。

在此用例中, 實現定制的可寫流 ,該將接受解析器的輸出並將行發送到數據庫。

然后您只需將管道調用鏈接為

fs.createReadStream(__dirname+'/fs_read.csv') .pipe(parser) .pipe(your_writable_stream)

當心此代碼立即返回。 它不等待操作完成。 它與node.js內部的隱藏事件循環進行交互。 事件循環經常使來自另一種語言的新開發人員感到困惑,他們習慣了命令式風格,而跳過了他們的node.js培訓這一部分。

實現這樣的定制可寫流可能會變得復雜,留給讀者練習。 如果解析器發出一行,這將是最簡單的,然后可以編寫編寫器來處理單行。 確保您能夠以某種方式注意到錯誤並拋出適當的異常,否則您將被不完整的結果所困擾,沒有警告或原因。

一種駭人聽聞的方法是將let parser = ... console.log(data)替換為自定義函數writeRowToSqlite(data) ,您必須編寫該函數才能實現自定義流。 由於異步API問題,使用return data沒有任何用處。 如您所見,它肯定無法將數據放入輸出變量中。


  1. 至於為什么修改后的過帳中的output不包含數據...

不幸的是,正如您發現的那樣,這通常是錯誤的:

const output = fs.createReadStream(__dirname + "/users.csv").pipe(parser); console.log(output);

在這里,變量output將是ReadableStream ,它與可讀流中包含的數據不同。 簡而言之,就像文件系統中有文件一樣,您可以獲得有關文件的各種系統信息,但是文件中包含的內容是通過不同的調用來訪問的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM