NodeJSを使用したCSVファイルの解析


125

nodejsを使用して、10000レコードの.csvファイルを解析し、各行でなんらかの操作を行います。http://www.adaltas.com/projects/node-csvを使用してみました。これを各行で一時停止させることができませんでした。これは、すべての10000レコードを読み取るだけです。次のことを行う必要があります。

  1. 行ごとにcsvを読み取る
  2. 各ラインで時間のかかる操作を実行する
  3. 次の行に行く

誰かがここで代替案を提案できますか?


多分それがあなたを助けるでしょう:stackoverflow.com/a/15554600/1169798
Sirko

1
各行にコールバックを追加しましたか?それ以外の場合は、それらをすべて非同期で読み取るだけです。
ベンフォーチュン

回答:


81

ストリームベースのソリューションを使用する必要があるようです。そのようなライブラリはすでに存在しているため、自分で再発明する前に、検証サポートも含まれているこのライブラリを試してください。https://www.npmjs.org/package/fast-csv


27
NodeCSVも十分にサポートされており、たまたまユーザーが約1桁増えています。 npmjs.com/package/csv
Steampowered

4
fast-csvは高速で使いやすく、使い始めることができます。
ロジャーガルソンニエト2017

1
URLでサポートされていますか?
DMS-KH

57

私はこのように使用しました:-

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
私は何か悪いことをしているかもしれませんが、これを実行すると、parse定義されていません。行方不明のものはありますか?実行npm install csv-parseしてコードにaddを追加するとvar parse = require("csv-parse");、機能します。あなたは本当にあなたの作品ですか?いずれかの方法で、私は私が含まれるように持っていても(このソリューションを愛しcsv-parseモジュールを
イアン・

1
あなたは正しい@lan、それはインクルードcsv-parseモジュールでなければなりません。
vineet

1
すばらしいです。回答を確認および更新していただき、ありがとうございます。
Ian

3
素晴らしい解決策。私のために働く。
Sun Bee

3
悲しいことに、これは悪いことです-巨大なファイルと長い行でエラーが発生しました...(メモリエラー-他の方法で読み取ることができますが)
Seti

55

私の現在のソリューションでは、非同期モジュールを使用して連続して実行します。

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
')'が恋しいと思いますか?
Steven Luong C

行14と15の最後に ')'を追加すると問題が解決するはずです。
Jon

@ShashankVivek-この古い回答(2015年以降)では、「async」は使用されるnpmライブラリです。もっとそれについてここcaolan.github.io/asyncは -多分このことができます理由を理解することはblog.risingstack.com/node-hero-async-programming-in-node-jsあなたの質問ならjavascriptのは2015年以来、多くの進化している、とより一般的には非同期については、これより多くの最近の記事を読まれmedium.com/@tkssharma/...
prule

15
  • このソリューションは、上記の回答の一部で使用されるcsv-parser代わりにをcsv-parse使用します。
  • csv-parserから約2年後 csv-parse
  • どちらも同じ目的を解決しますが、個人的にはcsv-parserヘッダーを処理するのが簡単なので、私はより良いことを発見しまし た。

最初にcsv-parserをインストールします。

npm install csv-parser

したがって、次のようなcsvファイルがあるとします。

NAME, AGE
Lionel Messi, 31
Andres Iniesta, 34

次のように、必要な操作を実行できます。

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

さらに読むために参照してください


13

fast-csvでストリーミングを一時停止するには、次のようにします。

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()とresume()は私が探していたものです!私のアプリケーションは、処理できるデータよりもはるかに速くデータを読み取るため、常にメモリ不足になります。
ehrhardt

@adnanこれを指摘してくれてありがとう。ドキュメントには記載されていませんが、それも私が探していたものです。
Piyush Beli、

10

参照しているnode-csvプロジェクトは、次のドキュメントから、CSVデータの大部分の各行を変換するタスクに完全に十分です: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());
    });
});

私の経験から、これはかなり高速な実装でもあると言えます。これは、1万レコード近くのデータセットで作業しており、処理時間はセット全体で数十ミリ秒という妥当なレベルでした。

Rearding jurkaのストリームベースのソリューションの提案を:ノード-CSVは、ストリームベースであり、Node.jsの次の「APIをストリーミングします。


8

高速CSV NPMモジュールは、データ・ライン・バイ・ラインcsvファイルからを読み取ることができます。

次に例を示します。

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にはありません。fromStream()そのプロジェクトサイトには例とドキュメントがありません。
Cees Timmerman、

3

私は非同期のcsvリーダーが必要で、元々は@Pransh Tiwariの答えを試しましたが、awaitおよびで動作させることができませんでしたutil.promisify()。最終的に私はnode-csvtojsonに出会いました。これはcsv-parserとほとんど同じですが、約束があります。次に、動作中のcsvtojsonの使用例を示します。

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

行ごとのnpmプラグインを試してください。

npm install line-by-line --save

5
プラグインのインストールは、尋ねられた質問ではありませんでした。プラグインの使用方法を説明するコードや、OPがプラグインを使用する理由を説明するコードを追加すると、はるかに有益です。
domdambrogia

2

これは外部URLからCSVファイルを取得するための私の解決策です

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

このタスクをawait / asyncで実行するための回避策:

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

2

わかりましたので、ここには多くの答えがあります。私が私のものと同じだと思う質問に答えるとは思いません。

データベースまたはサードパーティのAPIへの接続などの操作を行う必要がありますが、これは時間がかかり、非同期です。サイズが大きいなどの理由でドキュメント全体をメモリにロードしたくないので、処理するために行ごとに読み取る必要があります。

私はfs文書を読みましたが、読み取りが一時停止する可能性がありますが、.on( 'data')呼び出しを使用すると、これらの回答のほとんどが継続的に使用され、問題が発生します。


更新:ストリームについて、私が思っていたよりも多くの情報を知っています

これを行う最良の方法は、書き込み可能なストリームを作成することです。これにより、CSVデータが非同期呼び出しを管理できる書き込み可能なストリームにパイプされます。パイプはバッファーをリーダーまでずっと管理するので、大量のメモリを使用することはありません

シンプルバージョン

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)

クラスバージョン

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

古い方法:

読み取り可能な問題

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

あなたはreading旗に気づくでしょう。なんらかの理由でファイルの終わり近くにある.on( '読み取り可能')が小さなファイルと大きなファイルで2回目に呼び出されることに気づきました。理由はわかりませんが、これにより、2番目のプロセスが同じ広告申込情報を読み取ることができなくなります。


1

私はこの単純なものを使用します:https : //www.npmjs.com/package/csv-parser

使い方はとても簡単:

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

私は使用してcsv-parseいましたが、大きなファイルでパフォーマンスの問題が発生していました。私が見つけた優れたライブラリの1つはPapa Parseです。。ドキュメントは適切で、サポートがよく、軽量で、依存関係はありません。

インストール papaparse

npm install papaparse

使用法:

  • 非同期/待機
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()
  • 折り返し電話
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.'); 
  }
});

header: trueは設定のオプションです。他のオプションについてはドキュメントを参照してください


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モジュールを使用してcsvをjson形式に変換し、プログラムでjsonファイルを簡単に使用できます


-1

npmインストールcsv

サンプルCSVファイル解析するCSVファイルが必要になるので、CSVファイルを既に持っているか、以下のテキストをコピーして新しいファイルに貼り付け、そのファイルを「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

CSVファイルの読み取りと解析のサンプルコード

新しいファイルを作成し、それに次のコードを挿入します。舞台裏で起こっていることを必ずお読みください。

    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.

アプリを起動して機能を確認するコンソールを開き、次のコマンドを入力します。

ノードアプリ1ノードアプリコンソールに次の出力が表示されます。

[  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'}、]次に、Webブラウザーを開いてサーバーに移動します。JSON形式でデータを出力するはずです。

まとめnode.jsとそのCSVモジュールを使用すると、サーバーに格納されているデータをすばやく簡単に読み取って使用し、要求に応じてクライアントで使用できるようにすることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.