我正在使用一个库,ya-csv,期望文件或流作为输入,但我有一个字符串。
如何将该字符串转换为节点中的流?
我正在使用一个库,ya-csv,期望文件或流作为输入,但我有一个字符串。
如何将该字符串转换为节点中的流?
当前回答
下面是TypeScript中的一个简洁的解决方案:
import { Readable } from 'stream'
class ReadableString extends Readable {
private sent = false
constructor(
private str: string
) {
super();
}
_read() {
if (!this.sent) {
this.push(Buffer.from(this.str));
this.sent = true
}
else {
this.push(null)
}
}
}
const stringStream = new ReadableString('string to be streamed...')
其他回答
不要用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'事件不会被触发(流接口不需要)。
下面是TypeScript中的一个简洁的解决方案:
import { Readable } from 'stream'
class ReadableString extends Readable {
private sent = false
constructor(
private str: string
) {
super();
}
_read() {
if (!this.sent) {
this.push(Buffer.from(this.str));
this.sent = true
}
else {
this.push(null)
}
}
}
const stringStream = new ReadableString('string to be streamed...')
我厌倦了每六个月重新学习一次,所以我发布了一个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,它应该与大多数版本的节点兼容。
另一个解决方案是将read函数传递给Readable的构造函数(cf doc stream Readable options)
var s = new Readable({read(size) {
this.push("your string here")
this.push(null)
}});
例如,你可以使用s.pipe
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()