Node.js: lisez un fichier texte dans un tableau. (Chaque ligne est un élément dans le tableau.)

Je voudrais lire un très très grand fichier dans un tableau JavaScript dans node.js.

Donc, si le fichier est comme ceci:

first line two three ... ... 

J'aurais le tableau:

 ['first line','two','three', ... , ... ] 

La fonction ressemblerait à ceci:

 var array = load(filename); 

Par conséquent, l'idée de tout charger en tant que chaîne et ensuite de la diviser n'est pas acceptable.

Si vous pouvez utiliser les données finales dans un tableau alors, ne seriez-vous pas capable de l'intégrer à une chaîne et de la diviser, comme cela a été suggéré? Dans tous les cas, si vous souhaitez traiter le fichier une ligne à la fois, vous pouvez également essayer quelque chose comme ceci:

 var fs = require('fs'); function readLines(input, func) { var remaining = ''; input.on('data', function(data) { remaining += data; var index = remaining.indexOf('\n'); while (index > -1) { var line = remaining.substring(0, index); remaining = remaining.substring(index + 1); func(line); index = remaining.indexOf('\n'); } }); input.on('end', function() { if (remaining.length > 0) { func(remaining); } }); } function func(data) { console.log('Line: ' + data); } var input = fs.createReadStream('lines.txt'); readLines(input, func); 

EDIT: (en réponse au commentaire de phopkins ), je pense que (au moins dans les versions plus récentes) la sous-chaîne ne copie pas de données mais crée un objet SlicedString spécial (à partir d'un coup d'œil rapide au code source v8). Dans tous les cas, voici une modification qui évite la sous-chaîne mentionnée (testé sur un fichier plusieurs mégaoctets de "Tous les travaux et aucune pièce ne fait de Jack un garçon ennuyeux"):

 function readLines(input, func) { var remaining = ''; input.on('data', function(data) { remaining += data; var index = remaining.indexOf('\n'); var last = 0; while (index > -1) { var line = remaining.substring(last, index); last = index + 1; func(line); index = remaining.indexOf('\n', last); } remaining = remaining.substring(last); }); input.on('end', function() { if (remaining.length > 0) { func(remaining); } }); } 

Synchrone:

 var fs = require('fs'); var array = fs.readFileSync('file.txt').toString().split("\n"); for(i in array) { console.log(array[i]); } 

Asynchrone:

 var fs = require('fs'); fs.readFile('file.txt', function(err, data) { if(err) throw err; var array = data.toString().split("\n"); for(i in array) { console.log(array[i]); } }); 

Utilisation du module de ligne de lecture Node.js.

 var fs = require('fs'); var readline = require('readline'); var filename = process.argv[2]; readline.createInterface({ input: fs.createReadStream(filename), terminal: false }).on('line', function(line) { console.log('Line: ' + line); }); 

Avec un BufferedReader , mais la fonction doit être asynchrone:

 var load = function (file, cb){ var lines = []; new BufferedReader (file, { encoding: "utf8" }) .on ("error", function (error){ cb (error, null); }) .on ("line", function (line){ lines.push (line); }) .on ("end", function (){ cb (null, lines); }) .read (); }; load ("file", function (error, lines){ if (error) return console.log (error); console.log (lines); }); 

Utiliser readline ( documentation ). Voici un exemple en lisant un fichier css, en analysant les icônes et en les écrivant à json

 var results = []; var rl = require('readline').createInterface({ input: require('fs').createReadStream('./assets/stylesheets/_icons.scss') }); // for every new line, if it matches the regex, add it to an array // this is ugly regex :) rl.on('line', function (line) { var re = /\.icon-icon.*:/; var match; if ((match = re.exec(line)) !== null) { results.push(match[0].replace(".",'').replace(":",'')); } }); // readline emits a close event when the file is read. rl.on('close', function(){ var outputFilename = './icons.json'; fs.writeFile(outputFilename, JSON.stringify(results, null, 2), function(err) { if(err) { console.log(err); } else { console.log("JSON saved to " + outputFilename); } }); }); 

Ceci est une variation de la réponse ci-dessus par @mtomis.

Il crée un flux de lignes. Il émet des événements "de données" et "fin", vous permettant de gérer la fin du flux.

 var events = require('events'); var LineStream = function (input) { var remaining = ''; input.on('data', function (data) { remaining += data; var index = remaining.indexOf('\n'); var last = 0; while (index > -1) { var line = remaining.substring(last, index); last = index + 1; this.emit('data', line); index = remaining.indexOf('\n', last); } remaining = remaining.substring(last); }.bind(this)); input.on('end', function() { if (remaining.length > 0) { this.emit('data', remaining); } this.emit('end'); }.bind(this)); } LineStream.prototype = new events.EventEmitter; 

Utilisez-le comme enveloppe:

 var lineInput = new LineStream(input); lineInput.on('data', function (line) { // handle line }); lineInput.on('end', function() { // wrap it up }); 

J'ai eu le même problème, et je l'ai résolu avec le module ligne par ligne

https://www.npmjs.com/package/line-by-line

Au moins pour moi fonctionne comme un charme, en mode synchrone et asynchrone.

En outre, le problème avec les lignes qui terminent la terminaison \ n peut être résolu avec l'option:

 { encoding: 'utf8', skipEmptyLines: false } 

Traitement synchrone des lignes:

 var LineByLineReader = require('line-by-line'), lr = new LineByLineReader('big_file.txt'); lr.on('error', function (err) { // 'err' contains error object }); lr.on('line', function (line) { // 'line' contains the current line without the trailing newline character. }); lr.on('end', function () { // All lines are read, file is closed now. }); 

file.lines avec le paquet JFile

Pseudo

 var JFile=require('jfile'); var myF=new JFile("./data.txt"); myF.lines // ["first line","second line"] .... 

N'oubliez pas avant:

 npm install jfile --save