如何读取node.js中的整个文本流?

时间:2012-11-16 05:23:48

标签: javascript node.js stream stdin ringojs

在RingoJS中有一个名为read的{​​{3}},它允许您读取整个流,直到结束。这在您创建命令行应用程序时很有用。例如,您可以编写tac function,如下所示:

#!/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

这允许您启动shell并运行tac命令。然后根据需要输入任意数量的行,完成后可以按 Ctrl + D (或 Ctrl + Z 在Windows上)以发信号通知program

我想在node.js中做同样的事情,但我找不到任何会这样做的函数。我想过使用readSync库中的fs end of transmission来模拟如下,但无济于事:

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

function(第一个参数)是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中的字符串返回?代码示例非常有用。

4 个答案:

答案 0 :(得分:28)

由于node.js是面向事件和流的,因此没有API等待stdin和缓冲区结果结束,但是手动操作很容易

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解析器等已有的流解析器链)

答案 1 :(得分:14)

关键是要使用这两个Stream事件:

Event: 'data'
Event: 'end'

对于stream.on('data', ...),您应该将数据数据收集到缓冲区(如果是二进制)或字符串中。

对于on('end', ...),您应该使用已完成的缓冲区调用回调,或者如果您可以内联它并使用Promises库返回。

答案 2 :(得分:5)

该特定任务有一个模块,名为 concat-stream

答案 3 :(得分: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是一个流。