Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何从Node.Js中的字符串创建流?_Javascript_String_Node.js_Stream_Inputstream - Fatal编程技术网

Javascript 如何从Node.Js中的字符串创建流?

Javascript 如何从Node.Js中的字符串创建流?,javascript,string,node.js,stream,inputstream,Javascript,String,Node.js,Stream,Inputstream,我使用的是一个库,它需要一个文件或流作为输入,但我有一个字符串 如何将该字符串转换为节点中的流?JavaScript是duck类型的,所以如果您只是复制,它就可以正常工作。事实上,您可能无法实现这些方法中的大多数,或者只是将它们作为存根;您需要实现的只是库使用的内容。您也可以使用节点的预构建来处理事件,这样您就不必自己实现addListener 下面是如何在CoffeeScript中实现它: class StringStream extends require('events').EventEm

我使用的是一个库,它需要一个文件或流作为输入,但我有一个字符串


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

JavaScript是duck类型的,所以如果您只是复制,它就可以正常工作。事实上,您可能无法实现这些方法中的大多数,或者只是将它们作为存根;您需要实现的只是库使用的内容。您也可以使用节点的预构建来处理事件,这样您就不必自己实现
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

编辑:可能更好

我的旧答案文本保存在下面


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

例如:

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()
正如我在中所更正的,节点v10中的新功能使这更容易:

const Readable = require('stream').Readable;
const s = new Readable();
s._read = () => {}; // redundant? see update below
s.push('your text here');
s.push(null);
…之后,您可以将其免费提供或以其他方式传递给您的预期消费者

它不像一行程序那样干净,但它确实避免了额外的依赖性

(更新:到目前为止,在v0.10.26到v9.2.1中,如果您没有设置
\u read
,直接从REPL提示符调用
push
将导致
未实现的
异常崩溃。它不会在函数或脚本中崩溃。如果不一致性让您感到紧张,请将
noop
包含在咖啡脚本中:

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

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

有一个模块:


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

这是模块的核心:

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,它应该与大多数版本的node兼容。

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


例如,您可以在使用s.pipe后使用它,这里有一个简洁的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...')

从节点10.17开始,stream.Readable有一个
From
方法,可以从任何iterable(包括数组文本)轻松创建流:

请注意,至少在10.17和12.3之间,字符串本身是可读取的,因此
可读。from(“输入字符串”)
可以工作,但每个字符发出一个事件<代码>可读。from([“输入字符串])
将为数组中的每个项目(在本例中为一个项目)发出一个事件

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


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

解决方案1

您可以使用
fs
模块完成此操作。函数
fs.createReadStream()
允许您打开一个可读的流,您所要做的就是传递文件路径以开始流式处理

const fs = require('fs');

const readable_stream = fs.createReadStream('file_path');
解决方案2

如果不想创建文件,可以在内存中创建一个流并对其进行处理(例如,将其上载到某个地方)。​您可以使用
模块执行此操作。您可以从
模块导入
可读的
,并创建可读的流。创建对象时,还可以实现
read()
方法,该方法用于从内部缓冲区读取数据。如果没有可读取的数据,则返回
null
。可选的
size
参数指定要读取的特定字节数。如果未指定
size
参数,则将返回内部缓冲区中包含的所有数据

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

const readable_stream = new Readable({
  ​read(size) {
   ​// ...
​  }
});
解决方案3

当您通过网络获取某些内容时,可以像流一样获取这些内容(例如,您从某个API获取PDF文档)

解决方案4

第三方软件包可以支持创建流作为一项功能。这是使用
aws sdk
软件包的一种方法,该软件包通常用于将文件上载到
S3

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

我明白了:
TypeError:string不是string.CALL_NON_函数(native)
当我像
newstringstream(str.send()
那样使用它时,仅仅因为JavaScript使用duck类型并不意味着你应该重新发明轮子。节点已经为流提供了一个实现。只要创建一个新的
stream.Readable
实例,就像@Garth Kidd建议的那样。@Sukima:
stream.Readable
当我写这个答案时。我无法让zeMirco的解决方案在我的用例中运行,但是
resumer
运行得很好。谢谢@substack简历建议对我很有效。谢谢简历是伟大的,但“自动恢复流在nextTick”可以产生惊喜,如果你期待你可以传递流未知的消费者!我有一些代码,如果元数据的db保存成功,它会将内容流传输到文件。这是一个潜伏的错误,当db写入立即返回成功时,它碰巧成功了!后来,我将其重构到一个异步块中,突然,流永远无法读取。教训:如果您不知道谁将使用您的流,请坚持使用through().pause()。
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...')
const { Readable } = require("stream")

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

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

const readable_stream = fs.createReadStream('file_path');
const Readable = require('stream').Readable;

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

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