2012-11-16 72 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是流。