Mengurai file CSV menggunakan NodeJS

125

Dengan nodejs saya ingin mengurai file .csv dari 10.000 catatan dan melakukan beberapa operasi pada setiap baris. Saya mencoba menggunakan http://www.adaltas.com/projects/node-csv . Saya tidak bisa menghentikan ini di setiap baris. Ini baru saja membaca semua 10.000 rekaman. Saya perlu melakukan hal berikut:

  1. membaca csv baris demi baris
  2. melakukan operasi yang memakan waktu di setiap baris
  3. pergi ke baris berikutnya

Adakah yang bisa menyarankan ide alternatif di sini?

lonelymo
sumber
Mungkin itu akan membantu Anda: stackoverflow.com/a/15554600/1169798
Sirko
1
Apakah Anda menambahkan callback untuk setiap baris? Jika tidak, itu hanya akan membaca semuanya secara asynchronous.
Ben Fortune

Jawaban:

81

Sepertinya Anda perlu menggunakan beberapa solusi berbasis aliran, sudah ada perpustakaan seperti itu jadi sebelum menemukan kembali diri Anda sendiri, coba perpustakaan ini, yang juga mencakup dukungan validasi. https://www.npmjs.org/package/fast-csv

Risto Novik
sumber
27
NodeCSV juga didukung dengan baik dan kebetulan memiliki kira-kira satu urutan lebih banyak pengguna. npmjs.com/package/csv
steampowered
4
fast-csv cepat, mudah digunakan dan untuk memulai.
Roger Garzon Nieto
1
Apakah itu mendukung dengan url?
DMS-KH
57

Saya menggunakan cara ini: -

var fs = require('fs'); 
var parse = require('csv-parse');

var csvData=[];
fs.createReadStream(req.file.path)
    .pipe(parse({delimiter: ':'}))
    .on('data', function(csvrow) {
        console.log(csvrow);
        //do something with csvrow
        csvData.push(csvrow);        
    })
    .on('end',function() {
      //do something with csvData
      console.log(csvData);
    });
vineet
sumber
2
Saya mungkin melakukan sesuatu yang salah, tetapi ketika saya menjalankan ini, parsetidak ditentukan. Apakah ada sesuatu yang saya lewatkan? Ketika saya menjalankan npm install csv-parsedan kemudian menambahkan kode saya var parse = require("csv-parse");, maka itu berhasil. Apakah kamu yakin milikmu bekerja? Either way, saya suka solusi ini (bahkan jika saya harus menyertakan csv-parsemodul
Ian
1
Anda benar @lan, itu harus menyertakan csv-parsemodul.
vineet
1
Luar biasa, terima kasih telah memverifikasi dan memperbarui jawaban Anda!
Ian
3
Solusi bagus. Bekerja untuk saya.
Sun Bee
3
Sayangnya ini buruk - saya mendapat kesalahan dengan file besar dan antrean panjang .... (kesalahan memori - meskipun cara lain untuk membacanya - berfungsi)
Seti
55

Solusi saya saat ini menggunakan modul async untuk dijalankan secara seri:

var fs = require('fs');
var parse = require('csv-parse');
var async = require('async');

var inputFile='myfile.csv';

var parser = parse({delimiter: ','}, function (err, data) {
  async.eachSeries(data, function (line, callback) {
    // do something with the line
    doSomething(line).then(function() {
      // when processing finishes invoke the callback to move to the next one
      callback();
    });
  })
});
fs.createReadStream(inputFile).pipe(parser);
prule
sumber
1
Saya pikir Anda melewatkan beberapa ')'?
Steven Luong C
Saya pikir menambahkan ')' ke akhir baris 14 dan 15 harus memperbaiki masalah.
Jon
@ShashankVivek - dalam jawaban lama ini (dari 2015), 'async' adalah pustaka npm yang digunakan. Lebih lanjut tentang itu di sini caolan.github.io/async - untuk memahami mengapa mungkin ini membantu blog.risingstack.com/node-hero-async-programming-in-node-js Tetapi javascript telah banyak berkembang sejak 2015, dan jika pertanyaan Anda lebih lanjut tentang asinkron secara umum, maka baca artikel yang lebih baru ini medium.com/@tkssharma/…
prule
15
  • Solusi ini menggunakan csv-parseralih-alih csv-parsedigunakan dalam beberapa jawaban di atas.
  • csv-parserdatang sekitar 2 tahun kemudian csv-parse.
  • Keduanya menyelesaikan tujuan yang sama, tetapi secara pribadi saya telah menemukan yang csv-parserlebih baik, karena mudah untuk menangani header melalui itu.

Instal parser csv terlebih dahulu:

npm install csv-parser

Jadi misalkan Anda memiliki file csv seperti ini:

NAME, AGE
Lionel Messi, 31
Andres Iniesta, 34

Anda dapat melakukan operasi yang diperlukan sebagai:

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

fs.createReadStream(inputFilePath)
.pipe(csv())
.on('data', function(data){
    try {
        console.log("Name is: "+data.NAME);
        console.log("Age is: "+data.AGE);

        //perform the operation
    }
    catch(err) {
        //error handler
    }
})
.on('end',function(){
    //some final operation
});  

Untuk bacaan lebih lanjut lihat

Pransh Tiwari
sumber
13

Untuk menghentikan sementara streaming di fast-csv, Anda dapat melakukan hal berikut:

let csvstream = csv.fromPath(filePath, { headers: true })
    .on("data", function (row) {
        csvstream.pause();
        // do some heavy work
        // when done resume the stream
        csvstream.resume();
    })
    .on("end", function () {
        console.log("We are done!")
    })
    .on("error", function (error) {
        console.log(error)
    });
adnan kamili
sumber
csvstream.pause () dan resume () adalah apa yang saya cari! Aplikasi saya akan selalu kehabisan memori karena membaca data jauh lebih cepat daripada yang dapat diprosesnya.
ehrhardt
@adnan Terima kasih telah menunjukkan hal ini. Itu tidak disebutkan dalam dokumentasi dan itulah yang juga saya cari.
Piyush Beli
10

Proyek node-csv yang Anda rujuk sepenuhnya cukup untuk tugas mengubah setiap baris dari sebagian besar data CSV, dari dokumen di: http://csv.adaltas.com/transform/ :

csv()
  .from('82,Preisner,Zbigniew\n94,Gainsbourg,Serge')
  .to(console.log)
  .transform(function(row, index, callback){
    process.nextTick(function(){
      callback(null, row.reverse());
    });
});

Dari pengalaman saya, saya dapat mengatakan bahwa ini juga merupakan implementasi yang agak cepat, saya telah mengerjakannya pada kumpulan data dengan hampir 10k catatan dan waktu pemrosesan berada pada tingkat puluhan milidetik yang wajar untuk seluruh rangkaian.

Rearding jurka 's aliran solusi berbasis saran: simpul-csv IS aliran berdasarkan dan mengikuti Node.js' mengalir API.

krwck
sumber
8

The cepat-csv NPM modul dapat membaca data baris demi baris dari file csv.

Berikut ini contohnya:

let csv= require('fast-csv');

var stream = fs.createReadStream("my.csv");

csv
 .parseStream(stream, {headers : true})
 .on("data", function(data){
     console.log('I am one line of data', data);
 })
 .on("end", function(){
     console.log("done");
 });
ramachandrareddy reddam
sumber
1
[email protected] tidak memiliki fromStream()dan situs proyeknya tidak memiliki contoh & dokumentasi.
Cees Timmerman
3

Saya membutuhkan pembaca csv asinkron dan awalnya mencoba jawaban @Pransh Tiwari tetapi tidak dapat membuatnya berfungsi dengan awaitdan util.promisify(). Akhirnya saya menemukan node-csvtojson , yang fungsinya hampir sama dengan csv-parser, tetapi dengan promise. Berikut adalah contoh penggunaan csvtojson dalam tindakan:

const csvToJson = require('csvtojson');

const processRecipients = async () => {
    const recipients = await csvToJson({
        trim:true
    }).fromFile('./recipients.csv');

    // Code executes after recipients are fully loaded.
    recipients.forEach((recipient) => {
        console.log(recipient.name, recipient.email);
    });
};
alexkb.dll
sumber
2

Coba plugin npm baris demi baris.

npm install line-by-line --save
nickast
sumber
5
Memasang plugin bukanlah pertanyaan yang ditanyakan. Menambahkan beberapa kode untuk menjelaskan cara menggunakan plugin dan / atau menjelaskan mengapa OP harus menggunakannya akan jauh lebih menguntungkan.
domdambrogia
2

ini adalah solusi saya untuk mendapatkan file csv dari url eksternal

const parse = require( 'csv-parse/lib/sync' );
const axios = require( 'axios' );
const readCSV = ( module.exports.readCSV = async ( path ) => {
try {
   const res = await axios( { url: path, method: 'GET', responseType: 'blob' } );
   let records = parse( res.data, {
      columns: true,
      skip_empty_lines: true
    } );

    return records;
 } catch ( e ) {
   console.log( 'err' );
 }

} );
readCSV('https://urltofilecsv');
Andrea Perdicchia
sumber
2

Solusi untuk melakukan tugas ini dengan await / async :

const csv = require('csvtojson')
const csvFilePath = 'data.csv'
const array = await csv().fromFile(csvFilePath);
HMagdy
sumber
2

Ok jadi ada banyak jawaban di sini dan saya rasa mereka tidak menjawab pertanyaan Anda yang menurut saya mirip dengan saya.

Anda perlu melakukan operasi seperti menghubungi database atau api bagian ketiga yang akan memakan waktu dan asyncronus. Anda tidak ingin memuat seluruh dokumen ke dalam memori karena terlalu besar atau alasan lain sehingga Anda perlu membaca baris demi baris untuk memproses.

Saya telah membaca ke dokumen fs dan dapat berhenti saat membaca tetapi menggunakan panggilan .on ('data') akan membuatnya terus menerus yang sebagian besar dari jawaban ini menggunakan dan menyebabkan masalah.


PEMBARUAN: Saya tahu lebih banyak info tentang Aliran daripada yang saya inginkan

Cara terbaik untuk melakukannya adalah dengan membuat aliran yang dapat ditulis. Ini akan menyalurkan data csv ke aliran Anda yang dapat ditulis yang dapat Anda kelola panggilan asyncronus. Pipa akan mengelola buffer sampai ke pembaca sehingga Anda tidak akan menggunakan banyak memori

Versi Sederhana

const parser = require('csv-parser');
const stripBom = require('strip-bom-stream');
const stream = require('stream')

const mySimpleWritable = new stream.Writable({
  objectMode: true, // Because input is object from csv-parser
  write(chunk, encoding, done) { // Required
    // chunk is object with data from a line in the csv
    console.log('chunk', chunk)
    done();
  },
  final(done) { // Optional
    // last place to clean up when done
    done();
  }
});
fs.createReadStream(fileNameFull).pipe(stripBom()).pipe(parser()).pipe(mySimpleWritable)

Versi Kelas

const parser = require('csv-parser');
const stripBom = require('strip-bom-stream');
const stream = require('stream')
// Create writable class
class MyWritable extends stream.Writable {
  // Used to set object mode because we get an object piped in from csv-parser
  constructor(another_variable, options) {
    // Calls the stream.Writable() constructor.
    super({ ...options, objectMode: true });
    // additional information if you want
    this.another_variable = another_variable
  }
  // The write method
  // Called over and over, for each line in the csv
  async _write(chunk, encoding, done) {
    // The chunk will be a line of your csv as an object
    console.log('Chunk Data', this.another_variable, chunk)

    // demonstrate await call
    // This will pause the process until it is finished
    await new Promise(resolve => setTimeout(resolve, 2000));

    // Very important to add.  Keeps the pipe buffers correct.  Will load the next line of data
    done();
  };
  // Gets called when all lines have been read
  async _final(done) {
    // Can do more calls here with left over information in the class
    console.log('clean up')
    // lets pipe know its done and the .on('final') will be called
    done()
  }
}

// Instantiate the new writable class
myWritable = new MyWritable(somevariable)
// Pipe the read stream to csv-parser, then to your write class
// stripBom is due to Excel saving csv files with UTF8 - BOM format
fs.createReadStream(fileNameFull).pipe(stripBom()).pipe(parser()).pipe(myWritable)

// optional
.on('finish', () => {
  // will be called after the wriables internal _final
  console.log('Called very last')
})

METODE LAMA:

MASALAH DENGAN mudah dibaca

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

const processFileByLine = async(fileNameFull) => {

  let reading = false

  const rr = fs.createReadStream(fileNameFull)
  .pipe(csv())

  // Magic happens here
  rr.on('readable', async function(){
    // Called once when data starts flowing
    console.log('starting readable')

    // Found this might be called a second time for some reason
    // This will stop that event from happening
    if (reading) {
      console.log('ignoring reading')
      return
    }
    reading = true
    
    while (null !== (data = rr.read())) {
      // data variable will be an object with information from the line it read
      // PROCESS DATA HERE
      console.log('new line of data', data)
    }

    // All lines have been read and file is done.
    // End event will be called about now so that code will run before below code

    console.log('Finished readable')
  })


  rr.on("end", function () {
    // File has finished being read
    console.log('closing file')
  });

  rr.on("error", err => {
    // Some basic error handling for fs error events
    console.log('error', err);
  });
}

Anda akan melihat sebuah readingbendera. Saya perhatikan bahwa untuk beberapa alasan tepat di dekat akhir file .on ('readable') dipanggil untuk kedua kalinya pada file kecil dan besar. Saya tidak yakin mengapa tetapi ini memblokirnya dari proses kedua membaca item baris yang sama.

BrinkDaDrink
sumber
1

Saya menggunakan yang sederhana ini: https://www.npmjs.com/package/csv-parser

Sangat mudah digunakan:

const csv = require('csv-parser')
const fs = require('fs')
const results = [];

fs.createReadStream('./CSVs/Update 20191103C.csv')
  .pipe(csv())
  .on('data', (data) => results.push(data))
  .on('end', () => {
    console.log(results);
    console.log(results[0]['Lowest Selling Price'])
  });
Xin
sumber
1

Saya menggunakan csv-parsetetapi untuk file yang lebih besar mengalami masalah kinerja, salah satu perpustakaan terbaik yang saya temukan adalah Papa Parse , dokumen bagus, dukungan bagus, ringan, tidak ada ketergantungan.

Install papaparse

npm install papaparse

Pemakaian:

  • async / await
const fs = require('fs');
const Papa = require('papaparse');

const csvFilePath = 'data/test.csv'

// Function to read csv which returns a promise so you can do async / await.

const readCSV = async (filePath) => {
  const csvFile = fs.readFileSync(filePath)
  const csvData = csvFile.toString()  
  return new Promise(resolve => {
    Papa.parse(csvData, {
      header: true,
      transformHeader: header => header.trim(),
      complete: results => {
        console.log('Complete', results.data.length, 'records.'); 
        resolve(results.data);
      }
    });
  });
};

const test = async () => {
  let parsedData = await readCSV(csvFilePath); 
}

test()
  • panggilan balik
const fs = require('fs');
const Papa = require('papaparse');

const csvFilePath = 'data/test.csv'

const file = fs.createReadStream(csvFilePath);

var csvData=[];
Papa.parse(file, {
  header: true,
  transformHeader: header => header.trim(),
  step: function(result) {
    csvData.push(result.data)
  },
  complete: function(results, file) {
    console.log('Complete', csvData.length, 'records.'); 
  }
});

Catatan header: trueadalah opsi pada konfigurasi, lihat dokumen untuk opsi lainnya

Glen Thompson
sumber
0
fs = require('fs');
fs.readFile('FILENAME WITH PATH','utf8', function(err,content){
if(err){
    console.log('error occured ' +JSON.stringify(err));
 }
 console.log('Fileconetent are ' + JSON.stringify(content));
})
swapnil.dll
sumber
0

Anda dapat mengonversi csv ke format json menggunakan modul csv-to-json dan kemudian Anda dapat dengan mudah menggunakan file json di program Anda

Anuj Kumar
sumber
-1

npm install csv

Contoh file CSV Anda akan memerlukan file CSV untuk diurai, jadi Anda sudah memilikinya, atau Anda dapat menyalin teks di bawah ini dan menempelkannya ke file baru dan menamainya "mycsv.csv"

ABC, 123, Fudge
532, CWE, ICECREAM
8023, POOP, DOGS
441, CHEESE, CARMEL
221, ABC, HOUSE
1
ABC, 123, Fudge
2
532, CWE, ICECREAM
3
8023, POOP, DOGS
4
441, CHEESE, CARMEL
5
221, ABC, HOUSE

Contoh Kode Membaca dan Mengurai file CSV

Buat file baru, dan masukkan kode berikut ke dalamnya. Pastikan untuk membaca apa yang terjadi di balik layar.

    var csv = require('csv'); 
    // loads the csv module referenced above.

    var obj = csv(); 
    // gets the csv module to access the required functionality

    function MyCSV(Fone, Ftwo, Fthree) {
        this.FieldOne = Fone;
        this.FieldTwo = Ftwo;
        this.FieldThree = Fthree;
    }; 
    // Define the MyCSV object with parameterized constructor, this will be used for storing the data read from the csv into an array of MyCSV. You will need to define each field as shown above.

    var MyData = []; 
    // MyData array will contain the data from the CSV file and it will be sent to the clients request over HTTP. 

    obj.from.path('../THEPATHINYOURPROJECT/TOTHE/csv_FILE_YOU_WANT_TO_LOAD.csv').to.array(function (data) {
        for (var index = 0; index < data.length; index++) {
            MyData.push(new MyCSV(data[index][0], data[index][1], data[index][2]));
        }
        console.log(MyData);
    });
    //Reads the CSV file from the path you specify, and the data is stored in the array we specified using callback function.  This function iterates through an array and each line from the CSV file will be pushed as a record to another array called MyData , and logs the data into the console to ensure it worked.

var http = require('http');
//Load the http module.

var server = http.createServer(function (req, resp) {
    resp.writeHead(200, { 'content-type': 'application/json' });
    resp.end(JSON.stringify(MyData));
});
// Create a webserver with a request listener callback.  This will write the response header with the content type as json, and end the response by sending the MyData array in JSON format.

server.listen(8080);
// Tells the webserver to listen on port 8080(obviously this may be whatever port you want.)
1
var csv = require('csv'); 
2
// loads the csv module referenced above.
3

4
var obj = csv(); 
5
// gets the csv module to access the required functionality
6

7
function MyCSV(Fone, Ftwo, Fthree) {
8
    this.FieldOne = Fone;
9
    this.FieldTwo = Ftwo;
10
    this.FieldThree = Fthree;
11
}; 
12
// Define the MyCSV object with parameterized constructor, this will be used for storing the data read from the csv into an array of MyCSV. You will need to define each field as shown above.
13

14
var MyData = []; 
15
// MyData array will contain the data from the CSV file and it will be sent to the clients request over HTTP. 
16

17
obj.from.path('../THEPATHINYOURPROJECT/TOTHE/csv_FILE_YOU_WANT_TO_LOAD.csv').to.array(function (data) {
18
    for (var index = 0; index < data.length; index++) {
19
        MyData.push(new MyCSV(data[index][0], data[index][1], data[index][2]));
20
    }
21
    console.log(MyData);
22
});
23
//Reads the CSV file from the path you specify, and the data is stored in the array we specified using callback function.  This function iterates through an array and each line from the CSV file will be pushed as a record to another array called MyData , and logs the data into the console to ensure it worked.
24

25
var http = require('http');
26
//Load the http module.
27

28
var server = http.createServer(function (req, resp) {
29
    resp.writeHead(200, { 'content-type': 'application/json' });
30
    resp.end(JSON.stringify(MyData));
31
});
32
// Create a webserver with a request listener callback.  This will write the response header with the content type as json, and end the response by sending the MyData array in JSON format.
33

34
server.listen(8080);
35
// Tells the webserver to listen on port 8080(obviously this may be whatever port you want.)
Things to be aware of in your app.js code
In lines 7 through 11, we define the function called 'MyCSV' and the field names.

If your CSV file has multiple columns make sure you define this correctly to match your file.

On line 17 we define the location of the CSV file of which we are loading.  Make sure you use the correct path here.

Mulai Aplikasi Anda dan Verifikasi Fungsionalitas Buka konsol dan ketik Perintah berikut:

Aplikasi node 1 Aplikasi node Anda akan melihat output berikut di konsol Anda:

[  MYCSV { Fieldone: 'ABC', Fieldtwo: '123', Fieldthree: 'Fudge' },
   MYCSV { Fieldone: '532', Fieldtwo: 'CWE', Fieldthree: 'ICECREAM' },
   MYCSV { Fieldone: '8023', Fieldtwo: 'POOP', Fieldthree: 'DOGS' },
   MYCSV { Fieldone: '441', Fieldtwo: 'CHEESE', Fieldthree: 'CARMEL' },
   MYCSV { Fieldone: '221', Fieldtwo: 'ABC', Fieldthree: 'HOUSE' }, ]

1 [MYCSV {Fieldone: 'ABC', Fieldtwo: '123', Fieldthree: 'Fudge'}, 2 MYCSV {Fieldone: '532', Fieldtwo: 'CWE', Fieldthree: 'ICECREAM'}, 3 MYCSV {Fieldone: '8023', Fieldtwo: 'POOP', Fieldthree: 'DOGS'}, 4 MYCSV {Fieldone: '441', Fieldtwo: 'CHEESE', Fieldthree: 'CARMEL'}, 5 MYCSV {Fieldone: '221', Fieldtwo: 'ABC', Fieldthree: 'HOUSE'},] Sekarang Anda harus membuka browser web dan menavigasi ke server Anda. Anda harus melihatnya mengeluarkan data dalam format JSON.

Kesimpulan Menggunakan node.js dan modul CSV-nya, kita dapat dengan cepat dan mudah membaca dan menggunakan data yang disimpan di server dan membuatnya tersedia untuk klien berdasarkan permintaan

Rubin bhandari
sumber