2012-11-16 70 views
19

在RingoJS中有一個function,名爲read,它允許您讀取整個流直到到達末尾。這在您製作命令行應用程序時很有用。舉例如下,你可以寫一個tacprogram如何讀取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 

這可以讓你啓動一個程序並運行tac命令。然後你,你希望鍵入儘可能多的行,你就大功告成之後,你可以按Ctrl鍵+(在Windows或按Ctrl +ž)d信號的end of transmission

我想在node.js中做同樣的事情,但我找不到可以這樣做的任何函數。我想到了用readSyncfunctionfs庫模擬如下,但無濟於事:

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

file descriptor for stdin(第一個參數)是0。所以它應該讀取鍵盤上的數據。相反,它給了我下面的錯誤:

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) 

你會如何同步收集在輸入文本流中的所有數據,並恢復它作爲Node.js的一個字符串?一個代碼示例會非常有幫助。

+0

您無法在異步流中同步讀取。無論如何,你爲什麼要? – tjameson

+0

我正在嘗試做同樣的事情。原因是在我的程序中創建一個交互選項,這有很多原因。一個異步閱讀器不會幫助太多。 – ton

+0

這裏有一個方法https://www.npmjs。com/package/readline-sync:http://stackoverflow.com/questions/8452957/synchronously-reading-stdin-in-windows/27931290#27931290 – ton

回答

12

關鍵是要使用這兩個流事件:

Event: 'data' 
Event: 'end' 

stream.on('data', ...)你應該收集數據的數據到任何一個緩衝區(如果是二進制)或爲一個字符串。

對於on('end', ...)你應該調用一個回調,你完成的緩衝區,或者如果你可以內聯它並使用Promises庫返回。

27

隨着Node.js的是事件和麪向流沒有API等到標準輸入和緩衝的結果結束,但它很容易做手工

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

在它最好不要緩衝數據大多數情況下和處理傳入塊到達時(使用已經可用流解析器是XML或者zlib的還是自己的FSM解析器鏈)

+4

你可以執行'process.stdin.setEncoding('utf-8') ;'回調後的簡歷和'bug'已經是字符串了。 – Mitar

+2

類似,但使用'Buffer.concat()':http://stackoverflow.com/questions/10686617/how-can-i-accumulate-a-raw-stream-in-node-js#23304138 – joeytwiddle

+0

@Mitar:它是'buf',而不是'bug'。 – evandrix

5

沒有爲特定的任務模塊,叫concat-stream

+0

該模塊允許你用另一個字符串散佈這些塊。可能只對調試有用:https://www.npmjs.org/package/join-stream – joeytwiddle

4

讓我來說明StreetStrider的答案。

這裏是如何與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); 
}); 

做到這一點請注意,process.stdin是流。