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

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


当前回答

从节点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

其他回答

JavaScript是鸭子类型的,所以如果你只是复制一个可读流的API,它会工作得很好。事实上,你可能不能实现这些方法中的大多数,或者只是把它们作为存根;您需要实现的只是库使用的内容。您也可以使用Node预先构建的EventEmitter类来处理事件,因此您不必自己实现addListener等。

下面是如何在CoffeeScript中实现它:

class StringStream extends require('events').EventEmitter
  constructor: (@string) -> super()

  readable: true
  writable: false

  setEncoding: -> throw 'not implemented'
  pause: ->    # nothing to do
  resume: ->   # nothing to do
  destroy: ->  # nothing to do
  pipe: -> throw 'not implemented'

  send: ->
    @emit 'data', @string
    @emit 'end'

然后你可以这样使用它:

stream = new StringStream someString
doSomethingWith stream
stream.send()

只需创建一个流模块的新实例,并根据您的需要定制它:

var Stream = require('stream');
var stream = new Stream();

stream.pipe = function(dest) {
  dest.write('your string');
  return dest;
};

stream.pipe(process.stdout); // in this case the terminal, change to ya-csv

or

var Stream = require('stream');
var stream = new Stream();

stream.on('data', function(data) {
  process.stdout.write(data); // change process.stdout to ya-csv
});

stream.emit('data', 'this is my string');

在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();

编辑: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()

正如@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。)