Javascript 如何将Node.js流的内容读入字符串变量?

Javascript 如何将Node.js流的内容读入字符串变量?,javascript,node.js,stream,Javascript,Node.js,Stream,我正在攻击一个节点程序,该程序用于捕获SMTP电子邮件并对邮件数据进行操作。库以流的形式提供邮件数据,我不知道如何将其转换为字符串 我目前正在使用stream.pipe(process.stdout,{end:false})将其写入stdout,但是正如我所说的,我需要字符串形式的流数据,一旦流结束,我就可以使用它 如何将Node.js流中的所有数据收集到一个字符串中?(这个答案来自几年前,当时它是最好的答案。现在下面有一个更好的答案。我没有跟上Node.js的进度,我无法删除这个答案,因为它标

我正在攻击一个节点程序,该程序用于捕获SMTP电子邮件并对邮件数据进行操作。库以流的形式提供邮件数据,我不知道如何将其转换为字符串

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

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

(这个答案来自几年前,当时它是最好的答案。现在下面有一个更好的答案。我没有跟上Node.js的进度,我无法删除这个答案,因为它标记为“关于这个问题的正确答案”.如果您正在考虑向下单击,您希望我做什么?)

关键是使用的和事件。请收听以下活动:

stream.on('data',(chunk)=>{…});
stream.on('end',()=>{…});
当您收到
数据
事件时,将新的数据块添加到为收集数据而创建的缓冲区中

当您收到
end
事件时,如有必要,将完成的缓冲区转换为字符串。然后做你需要做的事情。

(这个答案是几年前的,当时它是最好的答案。现在下面有一个更好的答案。我没有跟上node.js的进度,我无法删除这个答案,因为它标记为“关于这个问题的正确”。如果你正在考虑向下单击,你想让我做什么?)

关键是使用的和事件。请收听以下活动:

stream.on('data',(chunk)=>{…});
stream.on('end',()=>{…});
当您收到
数据
事件时,将新的数据块添加到为收集数据而创建的缓冲区中


当您收到
end
事件时,如有必要,将完成的缓冲区转换为字符串。然后做你需要做的事情。

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

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文本产生不可预测的故障(它假定每个字符都适合一个字节),但您可能也不关心这一点。

希望这比上述答案更有用:

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文本产生不可预测的故障(它假定每个字符都适合一个字节),但您可能也不关心这一点。

从NodeJ开始,您应该这样做-始终记住字符串,而不知道编码只是一堆字节:

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);
})
从NodeJ开始,您应该这样做-始终记住一个字符串,而不知道编码只是一堆字节:

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

我通常使用这个简单的函数将流转换为字符串:

function streamToString(stream, cb) {
  const chunks = [];
  stream.on('data', (chunk) => {
    chunks.push(chunk.toString());
  });
  stream.on('end', () => {
    cb(chunks.join(''));
  });
}
用法示例:

let stream = fs.createReadStream('./myFile.foo');
streamToString(stream, (data) => {
  console.log(data);  // data is now my string variable
});

我通常使用这个简单的函数将流转换为字符串:

function streamToString(stream, cb) {
  const chunks = [];
  stream.on('data', (chunk) => {
    chunks.push(chunk.toString());
  });
  stream.on('end', () => {
    cb(chunks.join(''));
  });
}
用法示例:

let stream = fs.createReadStream('./myFile.foo');
streamToString(stream, (data) => {
  console.log(data);  // data is now my string variable
});

以上这些都不适合我。我需要使用缓冲区对象:

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

以上这些都不适合我。我需要使用缓冲区对象:

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

Streams没有简单的
.toString()
函数(我理解),也没有类似于
.toStringAsync(cb)
函数(我不理解)

因此,我创建了自己的助手函数:

var streamToString = function(stream, callback) {
  var str = '';
  stream.on('data', function(chunk) {
    str += chunk;
  });
  stream.on('end', function() {
    callback(str);
  });
}

// how to use:
streamToString(myStream, function(myStr) {
  console.log(myStr);
});

Streams没有简单的
.toString()
函数(我理解),也没有类似于
.toStringAsync(cb)
函数(我不理解)

因此,我创建了自己的助手函数:

var streamToString = function(stream, callback) {
  var str = '';
  stream.on('data', function(chunk) {
    str += chunk;
  });
  stream.on('end', function() {
    callback(str);
  });
}

// how to use:
streamToString(myStream, function(myStr) {
  console.log(myStr);
});

这对我很有用,基于:


这对我很有用,基于:


像流减速机这样的东西怎么样

下面是一个使用ES6类的示例,说明如何使用ES6类

var stream = require('stream')

class StreamReducer extends stream.Writable {
  constructor(chunkReducer, initialvalue, cb) {
    super();
    this.reducer = chunkReducer;
    this.accumulator = initialvalue;
    this.cb = cb;
  }
  _write(chunk, enc, next) {
    this.accumulator = this.reducer(this.accumulator, chunk);
    next();
  }
  end() {
    this.cb(null, this.accumulator)
  }
}

// just a test stream
class EmitterStream extends stream.Readable {
  constructor(chunks) {
    super();
    this.chunks = chunks;
  }
  _read() {
    this.chunks.forEach(function (chunk) { 
        this.push(chunk);
    }.bind(this));
    this.push(null);
  }
}

// just transform the strings into buffer as we would get from fs stream or http request stream
(new EmitterStream(
  ["hello ", "world !"]
  .map(function(str) {
     return Buffer.from(str, 'utf8');
  })
)).pipe(new StreamReducer(
  function (acc, v) {
    acc.push(v);
    return acc;
  },
  [],
  function(err, chunks) {
    console.log(Buffer.concat(chunks).toString('utf8'));
  })
);

像流减速机这样的东西怎么样

下面是一个使用ES6类的示例,说明如何使用ES6类

var stream = require('stream')

class StreamReducer extends stream.Writable {
  constructor(chunkReducer, initialvalue, cb) {
    super();
    this.reducer = chunkReducer;
    this.accumulator = initialvalue;
    this.cb = cb;
  }
  _write(chunk, enc, next) {
    this.accumulator = this.reducer(this.accumulator, chunk);
    next();
  }
  end() {
    this.cb(null, this.accumulator)
  }
}

// just a test stream
class EmitterStream extends stream.Readable {
  constructor(chunks) {
    super();
    this.chunks = chunks;
  }
  _read() {
    this.chunks.forEach(function (chunk) { 
        this.push(chunk);
    }.bind(this));
    this.push(null);
  }
}

// just transform the strings into buffer as we would get from fs stream or http request stream
(new EmitterStream(
  ["hello ", "world !"]
  .map(function(str) {
     return Buffer.from(str, 'utf8');
  })
)).pipe(new StreamReducer(
  function (acc, v) {
    acc.push(v);
    return acc;
  },
  [],
  function(err, chunks) {
    console.log(Buffer.concat(chunks).toString('utf8'));
  })
);

最干净的解决方案可能是使用“stringstream”包,该包将流转换为带有承诺的字符串

const streamString = require('stream-string')

streamString(myStream).then(string_variable => {
    // myStream was converted to a string, and that string is stored in string_variable
    console.log(string_variable)

}).catch(err => {
     // myStream emitted an error event (err), so the promise from stream-string was rejected
    throw err
})

最干净的解决方案可能是使用“stringstream”包,该包将流转换为带有承诺的字符串

const streamString = require('stream-string')

streamString(myStream).then(string_variable => {
    // myStream was converted to a string, and that string is stored in string_variable
    console.log(string_variable)

}).catch(err => {
     // myStream emitted an error event (err), so the promise from stream-string was rejected
    throw err
})

另一种方法是将流转换为承诺(参考下面的示例),并使用
然后
(或
等待
)将解析值分配给变量

function streamToString (stream) {
  const chunks = [];
  return new Promise((resolve, reject) => {
    stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
    stream.on('error', (err) => reject(err));
    stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
  })
}

const result = await streamToString(stream)

另一种方法是将流转换为承诺(参考下面的示例),并使用
然后
(或
等待
)将解析值分配给变量

function streamToString (stream) {
  const chunks = [];
  return new Promise((resolve, reject) => {
    stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
    stream.on('error', (err) => reject(err));
    stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
  })
}

const result = await streamToString(stream)

我更幸运地使用了这样的:

let string = '';
readstream
    .on('data', (buf) => string += buf.toString())
    .on('end', () => console.log(string));

我使用node
v9.11.1
readstream
是来自
http.get
回调的响应。

我更幸运地使用了这样的方法:

let string = '';
readstream
    .on('data', (buf) => string += buf.toString())
    .on('end', () => console.log(string));
我使用node
v9.11.1
readstream
是来自
http.get
回调的响应。

使用项目依赖项中可能已经存在的,这非常简单:

// imports
const { WritableStreamBuffer } = require('stream-buffers');
const { promisify } = require('util');
const { createReadStream } = require('fs');
const pipeline = promisify(require('stream').pipeline);

// sample stream
let stream = createReadStream('/etc/hosts');

// pipeline the stream into a buffer, and print the contents when done
let buf = new WritableStreamBuffer();
pipeline(stream, buf).then(() => console.log(buf.getContents().toString()));
使用您可能已经在项目依赖项中使用的方法,这非常简单:

// imports
const { WritableStreamBuffer } = require('stream-buffers');
const { promisify } = require('util');
const { createReadStream } = require('fs');
const pipeline = promisify(require('stream').pipeline);

// sample stream
let stream = createReadStream('/etc/hosts');

// pipeline the stream into a buffer, and print the contents when done
let buf = new WritableStreamBuffer();
pipeline(stream, buf).then(() => console.log(buf.getContents().toString()));
使用流行的(每周下载量超过500万次)和轻量级获取流库的简单方法:

使用流行的(每周下载量超过500万次)和轻量级获取流库的简单方法:

设置编码('utf8'); 干得好,上面是塞巴斯蒂安J

我有几行测试代码出现了“缓冲区问题”,添加了编码信息,解决了这个问题,见下文

演示问题 软件

// process.stdin.setEncoding('utf8');
process.stdin.on('data', (data) => {
    console.log(typeof(data), data);
});
process.stdin.setEncoding('utf8'); // <- Activate!
process.stdin.on('data', (data) => {
    console.log(typeof(data), data);
});
输入

输出

object <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64 0d 0a>
string hello world
输出

object <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64 0d 0a>
string hello world
设置编码('utf8'); 干得好,上面是塞巴斯蒂安J

我有几行测试代码出现了“缓冲区问题”,并添加了encodin