nodejsを使用して、10000レコードの.csvファイルを解析し、各行でなんらかの操作を行います。http://www.adaltas.com/projects/node-csvを使用してみました。これを各行で一時停止させることができませんでした。これは、すべての10000レコードを読み取るだけです。次のことを行う必要があります。
- 行ごとにcsvを読み取る
- 各ラインで時間のかかる操作を実行する
- 次の行に行く
誰かがここで代替案を提案できますか?
nodejsを使用して、10000レコードの.csvファイルを解析し、各行でなんらかの操作を行います。http://www.adaltas.com/projects/node-csvを使用してみました。これを各行で一時停止させることができませんでした。これは、すべての10000レコードを読み取るだけです。次のことを行う必要があります。
誰かがここで代替案を提案できますか?
回答:
ストリームベースのソリューションを使用する必要があるようです。そのようなライブラリはすでに存在しているため、自分で再発明する前に、検証サポートも含まれているこのライブラリを試してください。https://www.npmjs.org/package/fast-csv
私はこのように使用しました:-
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);
});
parse
定義されていません。行方不明のものはありますか?実行npm install csv-parse
してコードにaddを追加するとvar parse = require("csv-parse");
、機能します。あなたは本当にあなたの作品ですか?いずれかの方法で、私は私が含まれるように持っていても(このソリューションを愛しcsv-parse
モジュールを
csv-parse
モジュールでなければなりません。
私の現在のソリューションでは、非同期モジュールを使用して連続して実行します。
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);
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
});
さらに読むために参照してください
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)
});
参照している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をストリーミングします。
高速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");
});
fromStream()
そのプロジェクトサイトには例とドキュメントがありません。
私は非同期の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);
});
};
行ごとのnpmプラグインを試してください。
npm install line-by-line --save
これは外部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');
わかりましたので、ここには多くの答えがあります。私が私のものと同じだと思う質問に答えるとは思いません。
データベースまたはサードパーティの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番目のプロセスが同じ広告申込情報を読み取ることができなくなります。
私はこの単純なものを使用します: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'])
});
私は使用して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
は設定のオプションです。他のオプションについてはドキュメントを参照してください
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モジュールを使用すると、サーバーに格納されているデータをすばやく簡単に読み取って使用し、要求に応じてクライアントで使用できるようにすることができます。