2012-11-16 11 views
19

W RingoJS jest function o nazwie read, który umożliwia odczytanie całego strumienia do momentu, w którym zostanie osiągnięty koniec. Jest to przydatne, gdy tworzysz aplikację w linii poleceń. Na przykład można napisać tacprogram następująco:Jak odczytać cały strumień tekstowy w pliku node.js?

#!/usr/bin/env ringo 

var string = system.stdin.read(); // read the entire input stream 
var lines = string.split("\n"); // split the lines 

lines.reverse();     // reverse the lines 

var reversed = lines.join("\n"); // join the reversed lines 
system.stdout.write(reversed); // write the reversed lines 

To pozwala odpalić konsolę i uruchom komendę tac. Następnie wpisać wiele linii, jak chcesz i po skończysz można nacisnąć Ctrl + D (lub Ctrl + Z w systemie Windows), aby zasygnalizować end of transmission.

Chcę zrobić to samo w węźle node.js, ale nie mogę znaleźć żadnej funkcji, która by to zrobiła. Myślałem o użyciu readSyncfunction z biblioteki fs symulować następująco, ale bezskutecznie:

fs.readSync(0, buffer, 0, buffer.length, null); 

file descriptor for stdin (pierwszy argument) jest 0. Powinien więc odczytać dane z klawiatury. Zamiast tego daje mi następujący błąd:

Error: ESPIPE, invalid seek 
    at Object.fs.readSync (fs.js:381:19) 
    at repl:1:4 
    at REPLServer.self.eval (repl.js:109:21) 
    at rli.on.self.bufferedCmd (repl.js:258:20) 
    at REPLServer.self.eval (repl.js:116:5) 
    at Interface.<anonymous> (repl.js:248:12) 
    at Interface.EventEmitter.emit (events.js:96:17) 
    at Interface._onLine (readline.js:200:10) 
    at Interface._line (readline.js:518:8) 
    at Interface._ttyWrite (readline.js:736:14) 

Jak byś synchronicznie zebrać wszystkie dane w strumieniu tekstu wejściowego i zwraca go jako ciąg w node.js? Przykład kodu byłby bardzo pomocny.

+0

Nie można synchronicznie czytać w strumieniu asynchronicznym. Dlaczego tak chcesz? – tjameson

+0

Próbuję zrobić to samo. Powodem jest stworzenie interaktywnej opcji w moim programie, przydatnej z wielu powodów. Asynchroniczny czytnik nie pomaga za bardzo. – ton

+0

tutaj sposób https: //www.npmjs.com/pakiet/readline-sync: http://stackoverflow.com/questions/8452957/synchronously-reading-stdin-in-windows/27931290#27931290 – ton

Odpowiedz

12

Najważniejsze jest, aby korzystać z tych dwóch wydarzeń Stream:

Event: 'data' 
Event: 'end' 

Dla stream.on('data', ...) należy zebrać dane z danymi do dowolnego bufora (jeżeli jest binarny) lub na sznurku.

Dla on('end', ...) należy wywołać wywołanie zwrotne z wykonanym buforem lub można go wstawić i użyć funkcji powrotu przy użyciu biblioteki obietnic.

27

Jak node.js to wydarzenie i strumienia zorientowanych nie ma API poczekać do końca standardowego wejścia i wynik bufora, ale to łatwo zrobić ręcznie

var content = ''; 
process.stdin.resume(); 
process.stdin.on('data', function(buf) { content += buf.toString(); }); 
process.stdin.on('end', function() { 
    // your code here 
    console.log(content.split('').reverse().join('')); 
}); 

W większości przypadków lepiej nie do buforowania danych i proces przychodzące kawałki po przyjeździe (z użyciem łańcuch już dostępnych parserami strumieniowych, takich jak XML lub zlib lub własnego parsera FSM)

+4

Możesz zrobić "process.stdin.setEncoding ('utf-8') ; 'po wznowieniu i' bug' w oddzwonieniu będzie już ciągiem. – Mitar

+2

Podobne, ale używając 'Buffer.concat()': http://stackoverflow.com/questions/10686617/how-can-i-accumulate-a-raw-stream-in-node-js#23304138 – joeytwiddle

+0

@Mitar: to 'buf', a nie' bug'. – evandrix

5

jest to moduł dla danego zadania, zwany concat-stream.

+0

Ten moduł pozwala możesz przeplatać kawałki innym ciągiem. Prawdopodobnie jest to przydatne tylko przy debugowaniu: https://www.npmjs.org/package/join-stream – joeytwiddle

4

Pozwól mi zilustrować odpowiedź StreetStrider.

Oto jak to zrobić z concat-stream

var concat = require('concat-stream'); 

yourStream.pipe(concat(function(buf){ 
    // buf is a Node Buffer instance which contains the entire data in stream 
    // if your stream sends textual data, use buf.toString() to get entire stream as string 
    var streamContent = buf.toString(); 
    doSomething(streamContent); 
})); 

// error handling is still on stream 
yourStream.on('error',function(err){ 
    console.error(err); 
}); 

Uwaga process.stdin jest strumień.

Powiązane problemy