2015-01-18 13 views
7

Ich versuche, eine Datei Zeile für Zeile zu lesen, führen Sie eine Aktion aus, die einen Rückruf hat, und wenn die Funktion beendet Zeilenauslese fortzusetzen. Zum Beispiel:Nodejs - Zeile für Zeile aus Datei lesen, async Aktion für jede Zeile ausführen und reusme

var fs = require('fs'); 
var readline = require('readline'); 
var stream = require('stream'); 
var instream = fs.createReadStream('./phrases.txt'); 
var outstream = new stream; 
var rl = readline.createInterface(instream, outstream); 
rl.on('line', function (line) { 
    rl.pause(); 
    setTimeout(function() { 
    console.log('resuming'); 
    rl.resume(); 
    }, 2000); 
}); 

war ich unter dem Eindruck, das obige Beispiel sollte grundsätzlich eine Zeile gelesen, warte 2 Sekunden, console.log und dann in der nächsten Zeile fortgesetzt werden. Was wirklich passiert ist, dass es für die ersten 2 Sekunden wartet und spuckt dann heraus viele console.log

Antwort

1

Ein sehr schönen Line-Reader-Modul vorhanden ist, https://github.com/nickewing/line-reader

einfacher Code:

var lineReader = require('line-reader'); 
    lineReader.eachLine('file.txt', function(line, last) { 
     // do whatever you want with line... 
     console.log(line); 
     if(last){ 
     // or check if it's the last one 
     } 
    }); 

auch " java-Stil“Schnittstelle für mehr Kontrolle:

lineReader.open('file.txt', function(reader) { 
    if (reader.hasNextLine()) { 
    reader.nextLine(function(line) { 
     console.log(line); 
    }); 
    } 
}); 

andere kühle Lösung:

var fs = require('fs'), 
    sleep = require('sleep'), 
    readline = require('readline'); 

var rd = readline.createInterface({ 
    input: fs.createReadStream('phrases.txt'), 
    output: process.stdout, 
    terminal: false 
}); 

rd.on('line', function(line) { 
    console.log('-------') 
    console.log(line); 
    sleep.sleep(2) 

}); 
+3

Was über das Hinzufügen von Schlaf so cool (2)? – Dmitri

2

Kann dieser Code Ihnen helfen, bitte stimmen Sie, wenn die Antwort gut ist.

function createLineReader(fileName){ 
    var EM = require("events").EventEmitter 
    var ev = new EM() 
    var stream = require("fs").createReadStream(fileName) 
    var remainder = null; 
    stream.on("data",function(data){ 
     if(remainder != null){//append newly received data chunk 
      var tmp = new Buffer(remainder.length+data.length) 
      remainder.copy(tmp) 
      data.copy(tmp,remainder.length) 
      data = tmp; 
     } 
     var start = 0; 
     for(var i=0; i<data.length; i++){ 
      if(data[i] == 10){ //\n new line 
       var line = data.slice(start,i) 
       ev.emit("line", line) 
       start = i+1; 
      } 
     } 
     if(start<data.length){ 
      remainder = data.slice(start); 
     }else{ 
      remainder = null; 
     } 
    }) 

    stream.on("end",function(){ 
     if(null!=remainder) ev.emit("line",remainder) 
    }) 

    return ev 
} 


//---------main--------------- 
fileName = process.argv[2] 

lineReader = createLineReader(fileName) 
lineReader.on("line",function(line){ 
    console.log(line.toString()) 
    //console.log("++++++++++++++++++++") 
}) 
10

Line by Line Modul hilft Ihnen, große Textdateien, Zeile für Zeile zu lesen, ohne die Dateien in den Speicher zu puffern.

Sie können die Zeilen asynchron verarbeiten. Dies ist das Beispiel vorgesehen:

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) { 
    // pause emitting of lines... 
    lr.pause(); 

    // ...do your asynchronous line processing.. 
    setTimeout(function() { 

     // ...and continue emitting lines. 
     lr.resume(); 
    }, 100); 
}); 

lr.on('end', function() { 
    // All lines are read, file is closed now. 
}); 
+0

Das ist eigentlich synchron. Weil jede Zeile nur so lange bearbeitet wird, bis die letzte Zeile bearbeitet wurde? – Pao

+0

Dies sollte die akzeptierte Antwort sein. Es löst genau das, was die Frage verlangt. Nachdem ich mehrere Stunden lang versucht habe, dies selbst herauszufinden, habe ich diese Lösung letztendlich verwendet. –

+0

Dies ist die echte Antwort. Andere Module tun einfach so, als wären sie asynchron. Sie brauchen wirklich etwas wie Pausen-Stream. – mauron85

0
const readline = require('readline'); 
const fs = require('fs'); 

const rl = readline.createInterface({ 
    input: fs.createReadStream('sample.txt') 
}); 

rl.on('line', (line) => { 
    console.log(`Line from file: ${line}`); 
}); 

Quelle: https://nodejs.org/api/readline.html#readline_example_read_file_stream_line_by_line

+0

Dies ist wahrscheinlich die beste Antwort, keine zusätzlichen Module erforderlich, alle native node.js Module – Dmitri

+0

Obwohl Ihr Code sauberer ist, ist es funktional nicht anders als der Code in der Frage. Das Hinzufügen von setTimeout funktioniert genauso in Ihrem Code. Auch ich habe in den letzten paar Stunden nach einer Lösung für mein Problem gesucht. Es scheint keine gute native (eingebaute nodejs) Möglichkeit zu geben, laufende Aufgaben auszuführen, bevor mit der nächsten Zeile fortgefahren wird. –