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

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


当前回答

不要用Jo Liss的简历回答。这在大多数情况下都是可行的,但在我的案例中,它却让我花了4或5个小时去寻找漏洞。不需要第三方模块来做这件事。

新回答:

var Readable = require('stream').Readable

var s = new Readable()
s.push('beep')    // the string you want
s.push(null)      // indicates end-of-file basically - the end of the stream

这应该是一个完全兼容的可读流。有关如何正确使用流的更多信息,请参阅这里。

旧的回答: 只需要使用本地PassThrough流:

var stream = require("stream")
var a = new stream.PassThrough()
a.write("your string")
a.end()

a.pipe(process.stdout) // piping will work as normal
/*stream.on('data', function(x) {
   // using the 'data' event works too
   console.log('data '+x)
})*/
/*setTimeout(function() {
   // you can even pipe after the scheduler has had time to do other things
   a.pipe(process.stdout) 
},100)*/

a.on('end', function() {
    console.log('ended') // the end event will be called properly
})

注意,'close'事件不会被触发(流接口不需要)。

其他回答

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

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

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

在coffee-script:

class StringStream extends Readable
  constructor: (@str) ->
    super()

  _read: (size) ->
    @push @str
    @push null

使用它:

new StringStream('text here').pipe(stream1).pipe(stream2)

不要用Jo Liss的简历回答。这在大多数情况下都是可行的,但在我的案例中,它却让我花了4或5个小时去寻找漏洞。不需要第三方模块来做这件事。

新回答:

var Readable = require('stream').Readable

var s = new Readable()
s.push('beep')    // the string you want
s.push(null)      // indicates end-of-file basically - the end of the stream

这应该是一个完全兼容的可读流。有关如何正确使用流的更多信息,请参阅这里。

旧的回答: 只需要使用本地PassThrough流:

var stream = require("stream")
var a = new stream.PassThrough()
a.write("your string")
a.end()

a.pipe(process.stdout) // piping will work as normal
/*stream.on('data', function(x) {
   // using the 'data' event works too
   console.log('data '+x)
})*/
/*setTimeout(function() {
   // you can even pipe after the scheduler has had time to do other things
   a.pipe(process.stdout) 
},100)*/

a.on('end', function() {
    console.log('ended') // the end event will be called properly
})

注意,'close'事件不会被触发(流接口不需要)。

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