NodeJS kullanarak bir CSV dosyasını ayrıştırma


125

Nodejs ile 10000 kayıttan oluşan bir .csv dosyasını ayrıştırmak ve her satırda bazı işlemler yapmak istiyorum. Http://www.adaltas.com/projects/node-csv kullanmayı denedim . Bunu her satırda duraklatamadım. Bu sadece tüm 10000 kaydı okuyor. Aşağıdakileri yapmam gerekiyor:

  1. csv'yi satır satır oku
  2. her satırda zaman alıcı işlem gerçekleştirin
  3. sonraki satıra git

Burada herhangi bir alternatif fikir önerebilecek misiniz?


Belki bu size yardımcı olur: stackoverflow.com/a/15554600/1169798
Sirko

1
Her satır için geri arama eklediniz mi? Aksi takdirde, hepsini eşzamansız olarak okuyacaktır.
Ben Fortune

Yanıtlar:


81

Görünüşe göre akış tabanlı bir çözüm kullanmanız gerekiyor, bu tür kitaplıklar zaten vardı, bu yüzden kendinizi yeniden keşfetmeden önce, doğrulama desteği de içeren bu kitaplığı deneyin. https://www.npmjs.org/package/fast-csv


27
NodeCSV de iyi destekleniyor ve yaklaşık olarak bir kat daha fazla kullanıcıya sahip. npmjs.com/package/csv
steampowered

4
fast-csv hızlıdır, kullanımı kolaydır ve başlatılır.
Roger Garzon Nieto

1
Url ile destekliyor mu?
DMS-KH

57

Bu şekilde kullandım: -

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);
    });

2
Yanlış bir şey yapıyor olabilirim, ancak bunu çalıştırdığımda parsetanımlanmadı. Eksik bir şey mi var? Çalıştırdığımda npm install csv-parseve sonra koduma eklediğimde var parse = require("csv-parse");, o zaman çalışıyor. Sizinkinin çalıştığından emin misiniz? Her iki durumda da, bu çözümü seviyorum ( csv-parsemodülü
Ian,

1
haklısın @lan, csv-parsemodül içermeli .
vineet

1
Harika, cevabınızı doğruladığınız ve güncellediğiniz için teşekkür ederiz!
Ian

3
Güzel çözüm. Benim için çalışıyor.
Sun Bee

3
ne yazık ki bu kötü - büyük dosyalar ve uzun satırlarla ilgili hatalar aldım .... (hafıza hataları - diğer okuma yolları olsa da - işe yarıyor)
Seti

55

Mevcut çözümüm, seri olarak yürütmek için zaman uyumsuz modülü kullanıyor:

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);

1
Sanırım bazılarını özledin mi?
Steven Luong C

14 ve 15. satırların sonuna a ')' eklemenin sorunu çözeceğini düşünüyorum.
Jon

@ShashankVivek - bu eski yanıtta (2015'ten itibaren), 'eşzamansız' kullanılan bir npm kitaplığıdır. Bununla ilgili daha fazla bilgiyi burada bulabilirsiniz caolan.github.io/async - bunun neden yardımcı olabileceğini anlamak için blog.risingstack.com/node-hero-async-programming-in-node-js Ancak javascript 2015'ten beri çok gelişti ve sorunuz varsa genel olarak eşzamansız hakkında daha fazla bilgi için, daha sonra bu daha yeni makaleyi okuyun medium.com/@tkssharma/…
prule

15
  • Bu çözüm csv-parseryerine kullanırcsv-parse yukarıdaki yanıtların bazılarında .
  • csv-parser 2 yıl sonra geldi csv-parse .
  • Her ikisi de aynı amacı çözüyor, ancak kişisel csv-parserolarak daha iyisini buldum , çünkü başlıklarla başa çıkmak kolay.

Önce csv ayrıştırıcısını kurun:

npm install csv-parser

Bunun gibi bir csv dosyanız olduğunu varsayalım:

NAME, AGE
Lionel Messi, 31
Andres Iniesta, 34

Gerekli işlemi şu şekilde gerçekleştirebilirsiniz:

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
});  

Daha fazla okuma için bakın


13

Hızlı csv'de akışı duraklatmak için aşağıdakileri yapabilirsiniz:

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)
    });

csvstream.pause () ve resume () aradığım şey! Uygulamalarımın belleği her zaman biterdi çünkü verileri işleyebileceğinden çok daha hızlı okurdu.
ehrhardt

@adnan Bunu işaret ettiğiniz için teşekkürler. Belgelerde bahsedilmiyor ve ben de aradığım şey buydu.
Piyush Beli

10

Referans verdiğiniz node-csv projesi, http://csv.adaltas.com/transform/ adresindeki belgelerden CSV verilerinin büyük bir kısmının her satırını dönüştürme görevi için tamamen yeterlidir :

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

Tecrübelerime göre, oldukça hızlı bir uygulama olduğunu söyleyebilirim, onunla 10k'ye yakın kayıtlara sahip veri setleri üzerinde çalışıyorum ve işlem süreleri tüm set için makul onlarca milisaniye seviyesinde idi.

Jurka'nın akış tabanlı çözüm önerisini dikkate alırsak : node-csv IS akışı tabanlı ve Node.js'nin akış API'sini izliyor.


8

Hızla CSV npm modül veri hattını-by-line csv dosyasından okuyabilirsiniz.

İşte bir örnek:

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");
 });

1
fast-csv@4.0.2'de hiç yok fromStream()ve proje sitesinde örnekler ve belgeler yok.
Cees Timmerman

3

Async bir csv okuyucusuna ihtiyacım vardı ve başlangıçta @ Pransh Tiwari'nin cevabını denedim, ancak awaitve ile çalışmasını sağlayamadım util.promisify(). Sonunda node-csvtojson ile karşılaştım , ki bu da csv-ayrıştırıcı ile hemen hemen aynı şeyi yapar, ancak vaatlerle. İşte csvtojson uygulamasının örnek bir kullanımı:

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);
    });
};

2

Satır satır npm eklentisini deneyin.

npm install line-by-line --save

5
Bir eklenti kurmak sorulan soru değildi. Eklentinin nasıl kullanılacağını ve / veya OP'nin neden onu kullanması gerektiğini açıklamak için bazı kodlar eklemek çok daha faydalı olacaktır.
domdambrogia

2

bu, harici url'den csv dosyasını almak için benim çözümüm

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');

2

Bu görevi await / async ile yapmak için geçici çözüm :

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

2

Tamam, burada pek çok cevap var ve bence benimkine benzediğini düşündüğüm sorunuza cevap vereceklerini sanmıyorum.

Zaman alacak ve asenkron olan bir veritabanı veya üçüncü taraf api ile iletişim kurmak gibi bir işlem yapmanız gerekir. Belgenin tamamını büyük veya başka bir nedenle belleğe yüklemek istemezsiniz, bu nedenle işlem için satır satır okumanız gerekir.

Fs belgelerini okudum ve okumayı duraklatabilir, ancak .on ('data') çağrısının kullanılması, bu yanıtların çoğunun kullandığı ve soruna neden olan sürekli olmasını sağlayacaktır.


GÜNCELLEME: Akışlar hakkında istediğimden daha fazla bilgi biliyorum

Bunu yapmanın en iyi yolu yazılabilir bir akış oluşturmaktır. Bu, csv verilerini eşzamansız çağrıları yönetebileceğiniz yazılabilir akışınıza aktarır. Boru, tamponu okuyucuya kadar yönetecek, böylece yoğun bellek kullanımıyla uğraşmayacaksınız

Basit Sürüm

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)

Sınıf Sürümü

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')
})

ESKİ YÖNTEM:

OKUNABİLİR PROBLEM

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);
  });
}

Bir readingbayrak göreceksiniz . Bir nedenden dolayı dosyanın sonuna doğru .on ('okunabilir') küçük ve büyük dosyalarda ikinci kez çağrıldığını fark ettim. Neden olduğundan emin değilim, ancak bu aynı satır öğelerini okuyan ikinci bir işlemden bunu engelliyor.


1

Bu basit olanı kullanıyorum: https://www.npmjs.com/package/csv-parser

Kullanımı çok basit:

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'])
  });

1

Kullanıyordum csv-parseama daha büyük dosyalar için performans sorunları yaşanıyordu bulduğum en iyi kitaplıklardan biri Papa Parse dokümanlar iyi, iyi destek, hafif, hiçbir bağımlılıkları vardır.

Yüklemek papaparse

npm install papaparse

Kullanımı:

  • eşzamansız / bekleyin
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()
  • geri aramak
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.'); 
  }
});

Not header: trueyapılandırmada bir seçenektir, diğer seçenekler için dokümanlara bakın


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));
})

0

Csv-to-json modülünü kullanarak csv'yi json formatına dönüştürebilir ve ardından programınızda json dosyasını kolayca kullanabilirsiniz.


-1

npm csv yükle

Örnek CSV dosyası Ayrıştırmak için bir CSV dosyasına ihtiyacınız olacak, yani ya zaten bir tane var ya da aşağıdaki metni kopyalayıp yeni bir dosyaya yapıştırıp bu dosyayı "mycsv.csv" olarak adlandırabilirsiniz.

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

Örnek Kod Okuma ve CSV dosyasını Ayrıştırma

Yeni bir dosya oluşturun ve aşağıdaki kodu buna ekleyin. Perde arkasında neler olduğunu okuduğunuzdan emin olun.

    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.

Uygulamanızı başlatın ve İşlevselliği Doğrulayın Bir konsol açın ve aşağıdaki Komutu yazın:

Düğüm uygulaması 1 Düğüm uygulaması Konsolunuzda aşağıdaki çıktıyı görmelisiniz:

[  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'},] Şimdi bir web tarayıcısı açmalı ve sunucunuza gitmelisiniz. Verileri JSON biçiminde çıkardığını görmelisiniz.

Sonuç node.js ve onun CSV modülünü kullanarak, sunucuda depolanan verileri hızlı ve kolay bir şekilde okuyabilir ve kullanabilir ve istek üzerine istemcinin kullanımına sunabiliriz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.