我正在入侵一个Node程序,该程序使用SMTP协议捕获SMTP电子邮件并对邮件数据采取行动。库将邮件数据作为流提供,但我不知道如何将其转换为字符串。

我目前正在用stream.pipe(process. pipe)将其写入标准输出。stdout, {end: false}),但正如我所说的,我需要一个字符串中的流数据,一旦流结束,我就可以使用它。

我如何收集所有的数据从一个Node.js流到一个字符串?


当前回答

从nodejs文档中,你应该这样做——永远记住一个字符串,而不知道编码只是一堆字节:

var readable = getReadableStreamSomehow();
readable.setEncoding('utf8');
readable.on('data', function(chunk) {
  assert.equal(typeof chunk, 'string');
  console.log('got %d characters of string data', chunk.length);
})

其他回答

(这个答案是多年前的,当时它是最好的答案。下面有一个更好的答案。我没有跟上node.js,我不能删除这个答案,因为它被标记为“正确的这个问题”。如果你想按下,你想让我做什么?)

关键是使用可读流的数据和结束事件。听下面这些事件:

stream.on('data', (chunk) => { ... });
stream.on('end', () => { ... });

当您收到数据事件时,将新的数据块添加到为收集数据而创建的Buffer中。

当您接收到结束事件时,如果需要,将完成的Buffer转换为字符串。那就做你该做的事。

希望这比上面的答案更有用:

var string = '';
stream.on('data',function(data){
  string += data.toString();
  console.log('stream data ' + part);
});

stream.on('end',function(){
  console.log('final output ' + string);
});

请注意,字符串连接并不是收集字符串部分的最有效方法,但使用它是为了简单(也许您的代码并不关心效率)。

此外,对于非ascii文本,这段代码可能会产生不可预测的失败(它假设每个字符都适合一个字节),但也许您也不关心这一点。

这对我来说是有效的,并且基于Node v6.7.0文档:

let output = '';
stream.on('readable', function() {
    let read = stream.read();
    if (read !== null) {
        // New stream data is available
        output += read.toString();
    } else {
        // Stream is now finished when read is null.
        // You can callback here e.g.:
        callback(null, output);
    }
});

stream.on('error', function(err) {
  callback(err, null);
})

以上这些方法对我都没用。我需要使用Buffer对象:

  const chunks = [];

  readStream.on("data", function (chunk) {
    chunks.push(chunk);
  });

  // Send the buffer or you can put it into a var
  readStream.on("end", function () {
    res.send(Buffer.concat(chunks));
  });

还有一个是使用承诺的字符串:

function getStream(stream) {
  return new Promise(resolve => {
    const chunks = [];

    # Buffer.from is required if chunk is a String, see comments
    stream.on("data", chunk => chunks.push(Buffer.from(chunk)));
    stream.on("end", () => resolve(Buffer.concat(chunks).toString()));
  });
}

用法:

const stream = fs.createReadStream(__filename);
getStream(stream).then(r=>console.log(r));

如果需要,删除. tostring()以用于二进制数据。

更新:@AndreiLED正确地指出了字符串的问题。我不能得到一个流返回字符串与节点的版本,但api指出这是可能的。