Search code examples
node.jsnode-csv-parse

Does csv-parse allow you to read from file?


I'm learning how to use the csv-parse module for nodejs. I wrote this code and it works perfectly:

var fs = require('fs');
  
const fileName = './spreadsheet.csv';
const assert = require('assert');
const { parse } = require('csv-parse');

const records = [];
// Initialize the parser
const parser = parse({
  delimiter: ','
});
// Use the readable stream api to consume records
parser.on('readable', function(){
  let record;
  while ((record = parser.read()) !== null) {
    records.push(record);
  }
});
// Catch any error
parser.on('error', function(err){
  console.error(err.message);
});


fs.readFile(fileName, 'utf8', function (err, f) {
   if (err) {
      return console.error(err);
   }
   const rows = f.split("\r\n");
   
   for(let x in rows) {
       parser.write(rows[x]+"\n");
   }
   parser.end();

   console.log(records);
});

But right now, I depend on the fs module and fs.readFile to consume my csv file. Does the csv-parse have an option to read ffrom file? I ask because as you can see in my code, I ahve to specify my own line-break characters, which could differ between csv files. I thought maybe the csv-parse module would have something that can more readily address such a situation?


Solution

  • The parser object will do most of the work for you. It is expecting the data to arrive on its stream interface and it will do everything else. All you have to do is open a stream and the pipe it to the parser like this:

    fs.createReadStream(fileName).pipe(parser);
    

    And, here it is combined with your code:

    const fs = require('fs');
      
    const fileName = './spreadsheet.csv';
    const { parse } = require('csv-parse');
    
    const records = [];
    // Initialize the parser
    const parser = parse({
      delimiter: ','
    });
    // Use the readable stream api to consume records
    parser.on('readable', function(){
      let record;
      while ((record = parser.read()) !== null) {
        records.push(record);
      }
    });
    // Catch any error
    parser.on('error', function(err){
      console.error(err.message);
    });
    
    parser.on('end', function() {
        console.log(records);
    });
    
    // open the file and pipe it into the parser
    fs.createReadStream(fileName).pipe(parser);
    

    P.S. It's amazing that such a simple example of getting the CSV data from a file is not shown in the documentation (at least not anywhere I could find it). I'm also surprised, they don't offer an option where they will automatically read the data from the stream, instead requiring you to implement the readable event handler. Odd, for such an otherwise complete package.