Lire un fichier ou plus généralement un flux de données ligne par ligne est une opération triviale pour toutes les personnes connaissant la fonction fgets. Voici 4 méthodes pour résoudre cette problématique basique avec NodeJS :
0. String & Split
C'est la méthode la plus simple, il suffit de charger la totalité du fichier dans une chaîne de caractères puis découper cette chaîne en fonction du caractère \n
#!/usr/bin/env node
var buffer = '';
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function (chunk) {
buffer += chunk;
});
process.stdin.on('end', function () {
buffer.split('\n').forEach(function(line) {
process.stdout.write(line);
process.stdout.write('\n');
});
});
1. Module byline
#!/usr/bin/env node
var byline = require('byline');
process.stdin.resume();
process.stdin.setEncoding('utf8');
stream = byline.createLineStream(process.stdin);
stream.on('data', function(line) {
process.stdout.write(line);
process.stdout.write('\n');
});
stream.on('end', function() {
// Ended !
});
2. Module carrier
#!/usr/bin/env node
var carrier = require('carrier');
process.stdin.resume();
process.stdin.setEncoding('utf8');
carrier.carry(process.stdin, function(line) {
process.stdout.write(line);
process.stdout.write('\n');
});
3. Module line-reader
#!/usr/bin/env node
var lineReader = require('line-reader');
lineReader.eachLine('/dev/stdin', function(line, last) {
process.stdout.write(line);
process.stdout.write('\n');
});
4. Module node-each-line
#!/usr/bin/env node
var each_line = require('./each_line').each_line;
each_line(process.stdin, function (line) {
process.stdout.write(line);
});
Comparaison
Pour faire son choix, il est intéressant de comparer leur performance pour cela
on commence par les installer:
npm install byline npm install carrier npm install line-reader wget https://raw.github.com/aaronj1335/node-each-line/master/each_line.js
Ensuite, on utilise un fichier qui va générer quelques milliers de lignes :
#!/usr/bin/env node
for(var i = 1; i <= 100000; i++) {
process.stdout.write(i+'');
process.stdout.write('\n');
}
Reste à exécuter le tout :
$ time ./input.js | ./00.js >/dev/null
real 0m14.753s
user 0m14.973s
sys 0m1.288s
$ time ./input.js | ./01.js >/dev/null
real 0m11.714s
user 0m11.885s
sys 0m1.204s
$ time ./input.js | ./02.js >/dev/null
real 0m11.495s
user 0m11.761s
sys 0m1.164s
$ time ./input.js | ./03.js >/dev/null
node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Socket is not writable
at Socket._writeOut (net.js:391:11)
at Socket.write (net.js:377:17)
at Object.<anonymous> (/home/thouveni/Tests/node/lines/input.js:4:17)
at Module._compile (module.js:402:26)
at Object..js (module.js:408:10)
at Module.load (module.js:334:31)
at Function._load (module.js:293:12)
at Array.<anonymous> (module.js:421:10)
at EventEmitter._tickCallback (node.js:126:26)
real 0m0.057s
user 0m0.068s
sys 0m0.036s
$ time ./input.js | ./04.js >/dev/null
real 0m5.096s
user 0m5.764s
sys 0m0.624s
Conclusion
Le module line-reader ne fonctionne pas, à ignorer. Les modules carrier et byline sont équivalents. Et le script node-each-line est le plus rapide mais il ne permet pas d'intercepter la fin de fichier. Le choix est donc une affaire de gout. Personnellement, j'utilise byline.
Ce commentaire a été supprimé par l'auteur.
RépondreSupprimer