如何从Node.Js中创建流?

时间:2022-09-28 18:28:58

I am using a library, ya-csv, that expects either a file or a stream as input, but I have a string.

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

How do I convert that string into a stream in Node?

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

9 个解决方案

#1


126  

As @substack corrected me in #node, the new streams API in Node v10 makes this easier:

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

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

… after which you can freely pipe it or otherwise pass it to your intended consumer.

在此之后,您可以*地将其传递给您的目标客户。

It's not as clean as the resumer one-liner, but it does avoid the extra dependency.

它不像恢复者一行程序那样干净,但是它避免了额外的依赖。

(Update: in v0.10.26 through v9.2.1 so far, a call to push directly from the REPL prompt will crash with a not implemented exception if you didn't set _read. It won't crash inside a function or a script. If inconsistency makes you nervous, include the noop.)

(更新:到目前为止,在v0.10.26到v9.2.1中,如果没有设置_read,从REPL提示符直接推送的调用将会崩溃,并出现未实现的异常。它不会在函数或脚本中崩溃。如果不一致会让你紧张,那就把鼻子也算进去。

#2


75  

Do not use Jo Liss's resumer answer. It will work in most cases, but in my case it lost me a good 4 or 5 hours bug finding. There is no need for third party modules to do this.

不要使用Jo Liss的概括回答。它在大多数情况下都可以工作,但是在我的情况下,它丢失了我4到5个小时的错误发现。第三方模块不需要这样做。

NEW ANSWER:

新回答:

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

This should be a fully compliant Readable stream. See here for more info on how to use streams properly.

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

OLD ANSWER: Just use the native PassThrough stream:

旧的回答:使用原生的直通流:

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

Note that the 'close' event is not emitted (which is not required by the stream interfaces).

请注意,“关闭”事件没有发出(流接口不需要它)。

#3


27  

Just create a new instance of the stream module and customize it according to your needs:

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

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

#4


12  

Edit: Garth's answer is probably better.

编辑:加斯的回答可能更好。

My old answer text is preserved below.

我的老答案被保存在下面。


To convert a string to a stream, you can use a paused through stream:

要将字符串转换为流,可以通过流使用暂停:

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

Example:

例子:

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

#5


8  

There's a module for that: https://gist.github.com/kawanet/8aea35dc4a578f09757d

这里有一个模块:https://gist.github.com/kawanet/8aea35dc4a578f09757d

/**
* @see https://www.npmjs.com/package/string-to-stream
*/
var str = require('string-to-stream')
str('hi there').pipe(process.stdout) // => 'hi there' 

#6


6  

in coffee-script:

在coffee-script:

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

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

use it:

使用它:

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

#7


3  

I got tired of having to re-learn this every six months, so I just published an npm module to abstract away the implementation details:

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

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

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

This is the core of the module:

这是该模块的核心:

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 is the string that must be passed to the constructor upon invokation, and will be outputted by the stream as data. options are the typical options that may be passed to a stream, per the documentation.

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

According to Travis CI, it should be compatible with most versions of node.

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

#8


1  

JavaScript is duck-typed, so if you just copy a readable stream's API, it'll work just fine. In fact, you can probably not implement most of those methods or just leave them as stubs; all you'll need to implement is what the library uses. You can use Node's pre-built EventEmitter class to deal with events, too, so you don't have to implement addListener and such yourself.

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

Here's how you might implement it in CoffeeScript:

以下是如何在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'

Then you could use it like so:

那么你可以这样使用它:

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

#9


1  

Another solution is passing the read function to the constructor of Readable (cf doc stream readeable options)

另一个解决方案是将读函数传递给可读的构造函数(cf doc流可读选项)

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

you can after use s.pipe for exemple

你可以使用s。管道为例

#1


126  

As @substack corrected me in #node, the new streams API in Node v10 makes this easier:

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

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

… after which you can freely pipe it or otherwise pass it to your intended consumer.

在此之后,您可以*地将其传递给您的目标客户。

It's not as clean as the resumer one-liner, but it does avoid the extra dependency.

它不像恢复者一行程序那样干净,但是它避免了额外的依赖。

(Update: in v0.10.26 through v9.2.1 so far, a call to push directly from the REPL prompt will crash with a not implemented exception if you didn't set _read. It won't crash inside a function or a script. If inconsistency makes you nervous, include the noop.)

(更新:到目前为止,在v0.10.26到v9.2.1中,如果没有设置_read,从REPL提示符直接推送的调用将会崩溃,并出现未实现的异常。它不会在函数或脚本中崩溃。如果不一致会让你紧张,那就把鼻子也算进去。

#2


75  

Do not use Jo Liss's resumer answer. It will work in most cases, but in my case it lost me a good 4 or 5 hours bug finding. There is no need for third party modules to do this.

不要使用Jo Liss的概括回答。它在大多数情况下都可以工作,但是在我的情况下,它丢失了我4到5个小时的错误发现。第三方模块不需要这样做。

NEW ANSWER:

新回答:

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

This should be a fully compliant Readable stream. See here for more info on how to use streams properly.

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

OLD ANSWER: Just use the native PassThrough stream:

旧的回答:使用原生的直通流:

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

Note that the 'close' event is not emitted (which is not required by the stream interfaces).

请注意,“关闭”事件没有发出(流接口不需要它)。

#3


27  

Just create a new instance of the stream module and customize it according to your needs:

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

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

#4


12  

Edit: Garth's answer is probably better.

编辑:加斯的回答可能更好。

My old answer text is preserved below.

我的老答案被保存在下面。


To convert a string to a stream, you can use a paused through stream:

要将字符串转换为流,可以通过流使用暂停:

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

Example:

例子:

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

#5


8  

There's a module for that: https://gist.github.com/kawanet/8aea35dc4a578f09757d

这里有一个模块:https://gist.github.com/kawanet/8aea35dc4a578f09757d

/**
* @see https://www.npmjs.com/package/string-to-stream
*/
var str = require('string-to-stream')
str('hi there').pipe(process.stdout) // => 'hi there' 

#6


6  

in coffee-script:

在coffee-script:

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

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

use it:

使用它:

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

#7


3  

I got tired of having to re-learn this every six months, so I just published an npm module to abstract away the implementation details:

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

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

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

This is the core of the module:

这是该模块的核心:

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 is the string that must be passed to the constructor upon invokation, and will be outputted by the stream as data. options are the typical options that may be passed to a stream, per the documentation.

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

According to Travis CI, it should be compatible with most versions of node.

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

#8


1  

JavaScript is duck-typed, so if you just copy a readable stream's API, it'll work just fine. In fact, you can probably not implement most of those methods or just leave them as stubs; all you'll need to implement is what the library uses. You can use Node's pre-built EventEmitter class to deal with events, too, so you don't have to implement addListener and such yourself.

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

Here's how you might implement it in CoffeeScript:

以下是如何在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'

Then you could use it like so:

那么你可以这样使用它:

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

#9


1  

Another solution is passing the read function to the constructor of Readable (cf doc stream readeable options)

另一个解决方案是将读函数传递给可读的构造函数(cf doc流可读选项)

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

you can after use s.pipe for exemple

你可以使用s。管道为例