【问题标题】:Read csv file with nodejs with a max number rows使用具有最大行数的nodejs读取csv文件
【发布时间】:2021-03-18 22:07:26
【问题描述】:

我正在尝试使用 csv-parser 库读取带有 node.js 的 CSV 文件。

由于它是一个大文件,我需要检查标题和第一行 100 并停止该方法,如果一切正常,则返回 true,如果数据不符合条件,则返回 false

我怎样才能做到这一点?

这是我目前所拥有的:

const csv = require('csv-parser');
const fs = require('fs');    
exports.checkFileFormat = (file) => {
  let stream = fs.createReadStream(file.tempFilePath)
    .pipe(csv())
    .on('headers', (headers) => {
      /*...some logic...*/
    })
    .on('data', (row) => {
      if (!typeof (row["USAGE"]) == 'number'
          || !moment(row["START_DATE"], 'YYYYMMDD', true).isValid()
          || !moment(row["END_DATE"], 'YYYYMMDD', true).isValid()) {
        stream.unpipe(csv());
        return false;
      }       
    })
    .on('end', () => {
       console.log('CSV file successfully processed');
    });
    return true;
}

在之前的版本中,我还声明了:var num = 100 并在 .on('data', (row) => {...} 内部对其进行了测试,但它不起作用。

【问题讨论】:

  • 使函数 checkFileFormat 返回一个承诺。在 promise 内部,'.on('end') 回调中的 resolve(false) 代替了 return falseresolve(true)。我不完全确定这会奏效,但这就是我的处理方式
  • 我亲自测试了我的答案,它按预期工作。唯一的问题在于 stream.close() 函数,它显然不存在

标签: javascript node.js filestream node-csv-parse


【解决方案1】:

跟进我的评论

使函数checkFileFormat 返回一个承诺。在 promise 内部,resolve(false) 代替了 '.on('end') 回调中的 return falseresolve(true)。我不完全确定这会奏效,但这就是我的处理方式

const csv = require('csv-parser');
const fs = require('fs');

exports.checkFileFormat = (file) => {
    return new Promise((resolve, reject) => {
        let stream = fs.createReadStream(file.tempFilePath)
            .pipe(csv())
            .on('headers', (headers) => {
                /*...some logic...*/
            })
            .on('data', (row) => {
                if (!typeof (row["USAGE"]) == 'number'
                    || !moment(row["START_DATE"], 'YYYYMMDD', true).isValid()
                    || !moment(row["END_DATE"], 'YYYYMMDD', true).isValid()) {
                    stream.end(); // stream.unpipe(csv());
                    resolve(false);
                }
            })
            .on('end', () => {
                console.log('CSV file successfully processed');
                resolve(true);
            });
    });    
}

【讨论】:

  • 出于好奇 - 这真的有效吗?当条件满足时,您正在从stream 解压新的csv-stream。
  • 好吧,我不确定 unpipe 部分,它包含在 OP 的原始代码中,所以我认为他自己想出了那个部分。其他一切都有效,即Promise 机制。我在一个真实的例子中使用了这个代码,它吐出了正确的结果。但是不,我不知道unpipe(csv()) 是否适合在那里关闭流。
  • 感谢您的提示。我正在尝试将 Promise 与 @eol 代码结合起来。事实上unpipe(csv()) 没有按预期工作,当我上传第二个文件时,在第一个文件之后,我得到[ERR_STREAM_WRITE_AFTER_END]: write after end
  • @llandino 记录在案,而不是stream.unpipe(csv()),我认为@eol 是正确的,stream.end() 更可取。除此之外,这个答案是正确的。我将对其进行编辑以包含stream.end()
【解决方案2】:

如果你想读到一定数量的行然后换行,你可以尝试以下方法:

const csv = require('csv-parser');
const fs = require('fs');
let count = 0;
let maxLines = 3;
let fsStream = fs.createReadStream('./data.csv');
let csvStream = csv();

fsStream.pipe(csvStream)
    .on('headers', (headers) => {
        console.log(headers)
    })
    .on('data', (data) => {
        if (count >= maxLines) {
            fsStream.unpipe(csvStream);
            csvStream.end();
            fsStream.destroy();             
        } else {
            console.log(data);
            count++;
        }
    });

基本上,您只需计算每个读取行,当达到最大值时,您 unpipe 来自 fs-stream 的 csv-stream,然后是 end csv-stream,最后是 destroy fs-stream。

【讨论】:

  • 但是他需要从他的exports.checkFileFormat函数中得到结果
  • 谢谢@eol!它没有解决我的问题,但它比我第一次尝试在.on('data', (data) => {...}内部检查更正确
猜你喜欢
  • 2018-01-19
  • 2019-12-07
  • 2020-12-24
  • 2016-01-28
  • 1970-01-01
  • 2012-07-25
  • 2019-01-13
  • 1970-01-01
相关资源
最近更新 更多