2015-01-18 15 views
7

Próbuję odczytać plik wiersz po wierszu, wykonać pewne działanie, które ma wywołanie zwrotne i gdy funkcja kończy, aby wznowić czytanie linii. Na przykład:Nodejs - odczytaj wiersz po linii z pliku, wykonaj asynchroniczne działanie dla każdej linii i 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); 
}); 

byłem pod wrażeniem, powyższy przykład należy zasadniczo odczytać linię, odczekać 2 sekundy, console.log a następnie przejdź do następnego wiersza. Co naprawdę się dzieje, jest to, że czeka na pierwsze 2 sekundy, a następnie wypluwa się wiele console.log

Odpowiedz

1

moduł bardzo ładne line-czytnik istnieje, https://github.com/nickewing/line-reader

prosty kod:

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

również " java-style”interfejs dla lepszej kontroli:

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

Kolejny fajne rozwiązanie:

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

Co jest takiego fajnego dodanie snu (2)? – Dmitri

2

Kod ten może być pomocny, proszę zagłosować, jeśli odpowiedź jest dobra. Moduł

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 umożliwia czytanie dużych plików tekstowych, wiersz po wierszu, bez buforowania plików do pamięci.

Linie można przetwarzać asynchronicznie. Jest to przykład dostarczone:

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

To jest rzeczywiście synchroniczne. Ponieważ każda linia będzie przetwarzana tylko do czasu przetworzenia ostatniej linii? – Pao

+0

To powinna być zaakceptowana odpowiedź. Rozwiązuje dokładnie to, o co pyta. Po kilku godzinach próbowania tego na własną rękę, to jest rozwiązanie, którego użyłem w końcu. –

+0

To jest prawdziwa odpowiedź. Inne moduły po prostu udają asynchroniczne. Naprawdę potrzebujesz czegoś w rodzaju wstrzymania strumienia. – 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}`); 
}); 

źródło: https://nodejs.org/api/readline.html#readline_example_read_file_stream_line_by_line

+0

Jest to prawdopodobnie najlepsza odpowiedź, bez dodatkowych modułów, wszystkie natywne moduły node.js – Dmitri

+0

Chociaż twój kod jest czystszy, funkcjonalnie nie różni się od kodu w pytaniu. Dodanie setTimeout robi dokładnie to samo w twoim kodzie. Ja też szukałem rozwiązania mojego problemu przez ostatnie kilka godzin. Nie wydaje się, aby istniała jakakolwiek dobra natywna (wbudowana nodejs) sposób wykonywania uruchomionych zadań przed przejściem do następnej linii. –

Powiązane problemy