我正在使用一个库,ya-csv,期望文件或流作为输入,但我有一个字符串。

如何将该字符串转换为节点中的流?


当前回答

正如@substack在#node中纠正了我,node v10中的新streams API使这更容易:

const Readable = require('stream').Readable;
const s = new Readable();
s._read = () => {}; // redundant? see update below
s.push('your text here');
s.push(null);

之后,你可以自由地将它输送给你的目标客户。

它不像resumer一行程序那样简洁,但它确实避免了额外的依赖关系。

(更新:在v0.10.26到v9.2.1到目前为止,如果你没有设置_read,直接从REPL提示符调用push将会崩溃,并出现一个未实现的异常。它不会在函数或脚本中崩溃。如果前后矛盾让你紧张,那就加上noop。)

其他回答

在NodeJS中,你可以通过以下几种方式创建一个可读流:

解决方案1

你可以用fs模块来做。函数fs.createReadStream()允许你打开一个可读的流,你所要做的就是传递文件的路径来开始流。

const fs = require('fs');

const readable_stream = fs.createReadStream('file_path');

解决方案2

If you don't want to create file, you can create an in-memory stream and do something with it (for example, upload it somewhere). ​You can do this with stream module. You can import Readable from stream module and you can create a readable stream. When creating an object, you can also implement read() method which is used to read the data out of the internal buffer. If no data available to be read, null is returned. The optional size argument specifies a specific number of bytes to read. If the size argument is not specified, all of the data contained in the internal buffer will be returned.

const Readable = require('stream').Readable;

const readable_stream = new Readable({
  ​read(size) {
   ​// ...
​  }
});

解决方案3

当你通过网络获取一些东西时,它可以像流一样被获取(例如,你从一些API获取一个PDF文档)。

const axios = require('axios');

const readable_stream = await axios({
  method: 'get',
  url: "pdf_resource_url",
  responseType: 'stream'
}).data;

解决方案4

第三方包可以支持创建流作为一个特性。这是aws-sdk包的一种方法,通常用于将文件上传到S3。

const file = await s3.getObject(params).createReadStream();

从节点10.17,流。Readable有一个from方法,可以轻松地从任何可迭代对象(包括数组字面值)创建流:

const { Readable } = require("stream")

const readable = Readable.from(["input string"])

readable.on("data", (chunk) => {
  console.log(chunk) // will be called once with `"input string"`
})

请注意,至少在10.17和12.3之间,字符串本身是一个可迭代对象,因此Readable.from("input string")可以工作,但会为每个字符触发一个事件。Readable.from(["input string"])将为数组中的每一项触发一个事件(在本例中为一项)。

还要注意,在以后的节点中(可能是12.3,因为文档说函数在那时已经改变了),不再需要将字符串包装到数组中。

https://nodejs.org/api/stream.html#stream_stream_readable_from_iterable_options

我厌倦了每六个月重新学习一次,所以我发布了一个npm模块来抽象实现细节:

https://www.npmjs.com/package/streamify-string

这是该模块的核心:

const Readable = require('stream').Readable;
const util     = require('util');

function Streamify(str, options) {

  if (! (this instanceof Streamify)) {
    return new Streamify(str, options);
  }

  Readable.call(this, options);
  this.str = str;
}

util.inherits(Streamify, Readable);

Streamify.prototype._read = function (size) {

  var chunk = this.str.slice(0, size);

  if (chunk) {
    this.str = this.str.slice(size);
    this.push(chunk);
  }

  else {
    this.push(null);
  }

};

module.exports = Streamify;

STR是在调用时必须传递给构造函数的字符串,并将由流作为数据输出。根据文档,选项是可以传递给流的典型选项。

根据Travis CI,它应该与大多数版本的节点兼容。

编辑:Garth的答案可能更好。

我以前的答案文本保存在下面。


要将字符串转换为流,可以使用pause through流:

through().pause().queue('your string').end()

例子:

var through = require('through')

// Create a paused stream and buffer some data into it:
var stream = through().pause().queue('your string').end()

// Pass stream around:
callback(null, stream)

// Now that a consumer has attached, remember to resume the stream:
stream.resume()

另一个解决方案是将read函数传递给Readable的构造函数(cf doc stream Readable options)

var s = new Readable({read(size) {
    this.push("your string here")
    this.push(null)
  }});

例如,你可以使用s.pipe