如何在节点js中合并两个csv文件行

时间:2018-06-18 08:13:55

标签: node.js csv

我有2个csv文件,它们具有不同的不同数据但具有相同的标题 例如。 文件1 数据

"CODE","NAME","SUB_USER","SCORE"
"01","TEST","1","5"
"01","TEST","2","6"

其他文件 FILE2 有这样的数据

"CODE","NAME","SUB_USER","SCORE"
    "02","TEST2","3","5"
    "02","TEST2","4","6"

所以我想合并两个文件创建 FILE3 输出,就像这样

"CODE","NAME","SUB_USER","SCORE"
"01","TEST","1","5"
"01","TEST","2","6"
"02","TEST2","3","5"
"02","TEST2","4","6"

我试过下面的代码

var express = require('express');
var router = express.Router();
var fs = require('fs');
var parse = require('csv-parse');
var async = require('async');
var csv = require("fast-csv");

var file1 = appRoot + '\\csvFiles\\details1.csv';
var file2 = appRoot + '\\csvFiles\\details2.csv';
var stream = fs.createReadStream(file1);
var stream2 = fs.createReadStream(file2);
var fileData1 = [],
    fileData2 = [];
csv
    .fromStream(stream)
    .on("data", function(data) {
        fileData1.push(data);
    })
    .on("end", function() {
        console.log("done");
    });

csv
    .fromStream(stream2)
    .on("data", function(data) {
        fileData2.push(data);
    })
    .on("end", function() {
        console.log("done");
    });
var fileData3 = fileData1.concat(fileData2);

csv.writeToPath("outputfile.csv", fileData3).on("finish", function() {
    console.log("END");
});

但不工作不知道为什么?请帮我 /// *********************************************** *********************** // Thax寻求帮助,但我在这里遇到了新问题

以上代码开始工作后的一些更改

var file1 = appRoot + '\\csvFiles\\details1.csv';
var file2 = appRoot + '\\csvFiles\\idetails2.csv';
var stream = fs.createReadStream(file1);
var stream2 = fs.createReadStream(file2);
var fileData1 = [],
    fileData2 = [],
    i = 0;

csv.fromStream(stream).on("data", function(data) {
    fileData1.push(data);
}).on("end", function() {
    csv.fromStream(stream2).on("data", function(data) {
        if (i != 0) {
            fileData2.push(data);
        }
        i++;
    }).on("end", function() {
        console.log("done");
        var fileData3 = fileData1.concat(fileData2);
        csv.writeToPath("outputfile.csv", fileData3).on("finish", function() {
            res.send('Done merge');
        });
    });
});

但问题是如果我的文件数量增加那么我将如何处理该事情

1 个答案:

答案 0 :(得分:2)

这里最大的问题是一个非常普遍的问题。您执行异步任务,但在使用结果之前不要等待它们完成。

在" end"之前连接文件数据。调用每个任务的回调。 解决方案是等待每个回调被调用,然后处理数据。

我使用Promises

创建了一个小例子
const file1 = 'one.csv';
const file2 = 'two.csv';
const stream = fs.createReadStream(file1);
const stream2 = fs.createReadStream(file2);
const fileData1 = [];
const fileData2 = [];

const file1Promise = new Promise((resolve) => {
  csv
      .fromPath(file1, {headers: true})
      .on('data', function(data) {
        fileData1.push(data);
      })
      .on('end', function() {
        console.log('done');
        resolve();
      });
});

const file2Promise = new Promise((resolve) => {
  csv
      .fromPath(file2, {headers: true})
      .on('data', function(data) {
        fileData2.push(data);
      })
      .on('end', function() {
        console.log('done');
        resolve();
      });
});

Promise.all([
  file1Promise,
  file2Promise,
])
    .then(() => {
      const fileData3 = fileData1.concat(fileData2);
      console.log(fileData3);

      const csvStream = csv.format({headers: true});
      const writableStream = fs.createWriteStream('outputfile.csv');

      writableStream.on('finish', function() {
        console.log('DONE!');
      });

      csvStream.pipe(writableStream);
      fileData3.forEach((data) => {
        csvStream.write(data);
      });
      csvStream.end();
    });

我创建了一个可以轻松合并多个文件的函数:

function concatCSVAndOutput(csvFilePaths, outputFilePath) {
  const promises = csvFilePaths.map((path) => {
    return new Promise((resolve) => {
      const dataArray = [];
      return csv
          .fromPath(path, {headers: true})
          .on('data', function(data) {
            dataArray.push(data);
          })
          .on('end', function() {
            resolve(dataArray);
          });
    });
  });

  return Promise.all(promises)
      .then((results) => {

        const csvStream = csv.format({headers: true});
        const writableStream = fs.createWriteStream(outputFilePath);

        writableStream.on('finish', function() {
          console.log('DONE!');
        });

        csvStream.pipe(writableStream);
        results.forEach((result) => {
          result.forEach((data) => {
            csvStream.write(data);
          });
        });
        csvStream.end();

      });
}

示例用法

concatCSVAndOutput(['one.csv', 'two.csv'], 'outputfile.csv')
    .then(() => ...doStuff);