Node.Js의 문자열에서 스트림을 만드는 방법은 무엇입니까?


177

파일 또는 스트림을 입력으로 예상하는 ya-csv 라이브러리를 사용하고 있지만 문자열이 있습니다.

노드에서 해당 문자열을 스트림으로 어떻게 변환합니까?

답변:


27

노드 10.17부터 stream.Readable은 fromiterable (배열 리터럴 포함)에서 쉽게 스트림을 생성 하는 방법을 가지고 있습니다.

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


에 따르면 stream.Readable.from , 문자열 또는 버퍼를 필요가 없습니다 Readable.from (문자열) 또는 Readable.from (버퍼)를 호출하는 성능상의 이유로 다른 스트림 의미에 맞게 반복 될 수있다.
abbr

내 잘못이야. 이 기능은 10.7에서 추가되었으며 원래 설명한 방식대로 작동했습니다. 그 이후로 문자열을 더 이상 배열로 래핑 할 필요가 없습니다 (12.3부터 더 이상 각 문자를 개별적으로 반복하지 않음).
Fizker

186

으로 @substack이 저를 수정 #node , 새로운 스트림 API 노드 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까지는 설정하지 않은 경우 pushREPL 프롬프트에서 직접 호출 하면 not implemented예외 가 발생합니다 _read. 함수 나 스크립트 내에서 충돌 하지 않습니다 . 긴장, 포함하십시오 noop.)


6
로부터 문서 (링크) : "읽기 가능한 모든 스트림 구현은 제공해야합니다 _read기본 자원에서 데이터를 가져올 방법을."
Felix Rabe

2
@eye_mew 먼저 ( 'stream') 필요
Jim Jones

8
null스트림 버퍼에 밀어 넣습니까?
dopatraman

5
@dopatraman null은 모든 데이터를 읽고 스트림을 닫았다 고 스트림에 알려줍니다.
chrishiestand

2
이런 식으로하지 말아야 할 것 같습니다. 문서 인용 : "이 readable.push()메소드는 Readable Implementers에 의해서만 호출되며 readable._read()메소드 내에서만 호출됩니다 ."
Axel Rauschmayer

127

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'이벤트는 생성되지 않습니다 (스트림 인터페이스에는 필요하지 않음).


2
@Finn 인수가없는 경우 자바 스크립트에서 parens가 필요하지 않습니다
BT

2018 년에 "var"을 사용하지 마십시오! 하지만 const
stackdave

30

stream모듈 의 새 인스턴스를 만들고 필요에 따라 사용자 정의하십시오.

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

13
이 코드는 스트림 규칙을 위반합니다. pipe()최소한 대상 스트림을 반환해야합니다.
greim

2
이 코드를 사용하면 종료 이벤트가 호출되지 않습니다. 일반적으로 사용할 수있는 스트림을 만드는 좋은 방법은 아닙니다.
BT

12

편집 : Garth의 대답 이 더 낫습니다.

내 이전 답변 텍스트는 아래에 유지됩니다.


스트림에 문자열을 변환하려면, 당신은이 일시 사용 을 통해 스트림 :

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

사용 사례에 대해 zeMirco의 솔루션을 얻을 수 없었지만 resumer꽤 잘 작동했습니다. 감사!
mpen

@substack 이력서 제안은 저에게 매우 효과적이었습니다. 감사!
Garth Kidd

2
이력서는 훌륭하지만 "알려지지 않은 소비자에게 스트림을 전달할 수있을 것으로 예상되면"NextTick에서 스트림을 자동으로 다시 시작 "할 수 있습니다. 메타 데이터의 DB 저장에 성공하면 콘텐츠 스트림을 파일로 파이프하는 코드가 있습니다. 그것은 숨어있는 버그였습니다 .DB 쓰기가 즉시 성공을 반환했을 때 성공했습니다! 나중에 비동기 블록 내부에 있도록 리팩터링하고 스트림을 읽을 수 없었습니다. 레슨 : 스트림을 소비 할 사람을 모른다면 through (). pause (). queue ( 'string'). end () 기술을 고수하십시오.
Jolly Roger

1
이 답변의 이력서 부분을 사용했기 때문에 코드를 디버깅하는 데 약 5 시간이 걸렸습니다. 당신이 좋아할 수 있다면 좋을 것입니다. 그것을 제거
BT

10

그 모듈이 있습니다 : https://www.npmjs.com/package/string-to-stream

var str = require('string-to-stream')
str('hi there').pipe(process.stdout) // => 'hi there' 

1
"응용 프로그램이 있습니다"라는 말이 있습니까? ;)
masterxilo

1
코멘트의 링크는 유용한 것입니다 : npmjs.com/package/string-to-stream
Dem Pilafian

참고 로이 라이브러리를 사용하여 JSON을 Google 드라이브에 작성하려고 시도했지만 작동하지 않습니다. 여기에 대한 기사를 쓴 : medium.com/@dupski/...를 . 또한 아래 답변으로 추가됨
Russell Briggs

6

커피 스크립트에서 :

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

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

그걸 써:

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

6

다른 해결책은 read 함수를 Readable의 생성자에 전달하는 것입니다 (cf doc stream readeable 옵션 )

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

예를 들어 s.pipe를 사용한 후


마지막 귀국의 목적은 무엇입니까?
Kirill Reznikov

"항상 무언가 (또는 아무것도 반환하지 않음)"문서의 예입니다.
Philippe T.

JS에서 함수에 반환 값이 없으면 빈 반환 값과 같습니다. 찾은 링크를 제공해 주시겠습니까?
Kirill Reznikov

당신은 옳 아야합니다. 모범 사례로 더 많이 말했습니다. 아무 것도 돌려주고 싶지 않습니다. 실수가 아닙니다. 그래서 나는 선을 제거합니다.
Philippe T.

5

6 개월마다 이것을 다시 배우는 데 지쳤으므로 구현 세부 정보를 추상화하기 위해 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는 IS stringinvokation에 생성자로 전달되어야하며, 데이터 등의 스트림으로 출력 될 것이다. 설명서에options 따라 스트림으로 전달 될 수있는 일반적인 옵션입니다. .

Travis CI에 따르면 대부분의 노드 버전과 호환되어야합니다.


2
처음 에이 글을 올렸을 때 관련 코드가 포함되어 있지 않았습니다.
Chris Allen Lane

2

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

1

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

나는 이것을 얻는다 : TypeError: string is not a function at String.CALL_NON_FUNCTION (native) 내가 그것을 사용할 때new StringStream(str).send()
pathikrit

JavaScript가 오리 타이핑을 사용한다고해서 휠을 재발 명해야한다는 의미는 아닙니다. 노드는 이미 스트림 구현을 제공합니다. stream.Readable@Garth Kidd가 제안한 것과 같은 새로운 인스턴스를 만드십시오.
Sukima

4
@ 스키 키마 : 이 답변을 쓸 때 stream.Readable 존재하지 않았습니다 .
icktoofay
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.