읽을 수있는 스트림을 닫는 방법 (종료 전)?


90

Node.js에서 읽을 수있는 스트림 을 닫는 방법은 무엇입니까?

var input = fs.createReadStream('lines.txt');

input.on('data', function(data) {
   // after closing the stream, this will not
   // be called again

   if (gotFirstLine) {
      // close this stream and continue the
      // instructions from this if
      console.log("Closed.");
   }
});

이것은 다음보다 낫습니다.

input.on('data', function(data) {
   if (isEnded) { return; }

   if (gotFirstLine) {
      isEnded = true;
      console.log("Closed.");
   }
});

그러나 이것은 읽기 과정을 멈추지 않습니다 ...


6
경고 :이 질문은 fs모듈 컨텍스트에만 해당됩니다 . close에 존재하지 않습니다 Stream.Readable.
zamnuts 2014

3
좋은 소식. Node 버전 8이 제공합니다stream.destroy()
joeytwiddle

전화 할 수 readable.push(null) && readable.destroy();
Alexander Mills

답변:


39

호출 input.close(). 문서에는 없지만

https://github.com/joyent/node/blob/cfcb1de130867197cbc9c6012b7e84e08e53d032/lib/fs.js#L1597-L1620

명확하게 작업을 수행합니다 isEnded. :) 실제로 .

2015 년 4 월 19 일 수정 아래 의견을 바탕으로 명확히하고 업데이트합니다.

  • 이 제안은 해킹이며 문서화되지 않았습니다.
  • 현재를 lib/fs.js살펴보면 1.5 년이 지난 후에도 여전히 작동합니다.
  • destroy()선호 하는 전화 에 대한 아래 의견에 동의합니다 .
  • 아래에서 올바르게 언급했듯이 이것은 fs ReadStreams일반이 아닌의Readable

일반적인 솔루션에 관해서는 : 적어도 문서에 대한 이해와 _stream_readable.js.

내 제안은 읽기 가능한 스트림을 일시 중지 모드로 설정하여 적어도 업스트림 데이터 소스에서 추가 처리를 방지합니다. 문서 에서 언급했듯이 실제로 일시 중지 되도록 unpipe()모든 data이벤트 리스너를 잊지 말고 제거하십시오.pause()


더 길게 만들기 : 문서에서 참조를 추가하세요! :-)
Ionică Bizău

2
아주 좋아요! 소스 코드는 최고의 문서 리소스 인 것 같습니다. ;-)
Ionică Bizău

사실 나는 destroy대신 전화 하는 것을 선호 합니다. 적어도 autoClose를 true로 설정하면 호출됩니다. 소스 코드 (오늘)의 차이가 최소 (이다 살펴보면 destroy전화 close)하지만 미래에 변경 될 수 있습니다
마르셀 디 니즈

@NitzanShaked 파일이 업데이트되었습니다. 이것이 올바른 링크 입니까 : github.com/joyent/node/blob/… ? (이것은 미래에 변경 될 실 거예요 그래서, 커밋 ID를 포함)
Ionică Bizău

4
close()읽을 수있는 개체 가 없습니다 . 솔루션이 없습니까? 내 데이터 교환은 항상 불완전합니다 ...
CodeManX 2014

74

편집 : 좋은 소식입니다! Node.js 8.0.0부터 readable.destroy공식적으로 사용할 수 있습니다 : https://nodejs.org/api/stream.html#stream_Readable_destroy_error

ReadStream.destroy

언제든지 ReadStream.destroy 함수를 호출 할 수 있습니다 .

var fs = require('fs');

var readStream = fs.createReadStream('lines.txt');
readStream
    .on('data', function (chunk) {
        console.log(chunk);
        readStream.destroy();
    })
    .on('end', function () {
        // This may not been called since we are destroying the stream
        // the first time 'data' event is received
        console.log('All the data in the file has been read');
    })
    .on('close', function (err) {
        console.log('Stream has been destroyed and file has been closed');
    });

공용 함수 ReadStream.destroy는 문서화되어 있지 않지만 (Node.js v0.12.2) GitHub 에서 소스 코드를 볼 수 있습니다 ( 2012 년 10 월 5 일 commit ).

destroy기능은 내부적으로 표시 ReadStream파괴되어 호출로 인스턴스를 close파일을 해제하는 기능.

close 이벤트 를 수신 하여 파일이 언제 닫혔는지 정확히 알 수 있습니다 . 종료 이벤트는 데이터가 완전히 소모되지 않는 한 발생하지 않습니다.


합니다 destroy(그리고 close) 기능에 고유 fs.ReadStream . 일반 stream.Readable "인터페이스"의 일부가 없습니다 .


적어도 최신 버전의 Node (다른 항목을 확인하지 않음)에서는 파일 설명자가 자동으로 닫힙니다 . 즉, 스트림 error이 읽히지 않으면 결국 실행 되는지 확인하기 위해 어떤 종류의 철저한 테스트를 수행하지 않았습니다 . 그 외에도 제가 걱정할 유일한 다른 유출은 이벤트 핸들러입니다. 다시 한 번 말씀 드리지만 100 % 확실하지는 않지만 2010 년에는 괜찮을 수도 있습니다. Isaacs의 복음은 핸들러가 이미 터가 gc'd 일 때 정리 됨 : groups.google.com/d/msg/nodejs/pXbJVo0NtaY/BxUmF_jp9LkJ
mikermcneil 2015

1
데이터가 너무 작 으면은 on('data') 한 번만 트리거되므로는 발생하지 않고 .close()다른 사람에게 상기시킵니다.
bitfishxyz


12

당신은 할 수 없습니다. Node 5.3.0부터 일반 읽기 가능 스트림 을 닫거나 / 종료 / 중단 / 파괴하는 문서화 된 방법이 없습니다 . 이것은 노드 스트림 아키텍처의 제한 사항입니다.

여기에 다른 답변이 설명했듯이 fs.ReadStream 과 같이 Node에서 제공하는 Readable의 특정 구현에 대한 문서화되지 않은 해킹이 있습니다 . 이것은 Readable에 대한 일반적인 솔루션이 아닙니다.

누군가 여기에서 내가 틀렸다는 것을 증명할 수 있다면 그렇게하십시오. 불가능하다고 말하는 것을 할 수 있기를 바라며, 시정되어 기쁩니다.

편집 : 내 해결 방법은 다음과 같습니다 . 복잡한 일련의 호출을 통해 파이프 라인을 구현하십시오 . .destroy()unpipe()그리고 그 모든 복잡성 이 있지만 모든 경우에 제대로 작동하지 않습니다 .

편집 : Node v8.0.0 destroy()은 읽기 가능한 스트림 에 대한 API를 추가했습니다 .


1
이제는 stream.pipeline"오류 전달 및 적절한 정리를 처리하고 파이프 라인이 완료되면 콜백을 제공"한다고 주장하는이 있습니다. 도움이 되나요?
andrewdotn

11

버전 4.*.*에서 스트림에 null 값을 푸시하면 EOF신호 가 트리거됩니다 .

로부터 nodejs 워드 프로세서

null 이외의 값이 전달되면 push () 메서드는 후속 스트림 프로세서가 사용할 데이터 청크를 대기열에 추가합니다. null이 전달되면 스트림의 끝 (EOF)을 알리고 더 이상 데이터를 쓸 수 없습니다.

이 페이지에서 다른 많은 옵션을 시도한 후에 이것은 나를 위해 일했습니다.


1
나를 위해 작동합니다. 그러나 예상되는 동작, 즉 전체 스트림이 중지되도록 null을 푸시 한 후 done () 콜백을 호출하지 않아야했습니다.
Rich Apodaca

6

파괴 모듈은 스트림이 파괴되고 다른 API와 Node.js 버그를 처리하도록하기위한 것입니다. 지금은 최선의 선택 중 하나입니다.

NB. 노드 10에서는 .destroy추가 종속성없이 메서드를 사용할 수 있습니다 .


3

를 사용하여 스트림을 지우고 닫을 수 있습니다. 그러면 스트림의 yourstream.resume()모든 항목이 덤프되고 결국 닫힙니다.

로부터 공식 문서 :

Readable.resume () :

귀국 :이

이 메서드는 읽을 수있는 스트림이 '데이터'이벤트 생성을 다시 시작하도록합니다.

이 방법은 스트림을 흐름 모드로 전환합니다. 스트림에서 데이터를 사용하고 싶지 않지만 'end'이벤트를 얻으려면 stream.resume ()을 호출하여 데이터 흐름을 열 수 있습니다.

var readable = getReadableStreamSomehow();
readable.resume();
readable.on('end', () => {
  console.log('got to the end, but did not read anything');
});

이를 스트림 "배수"라고 할 수 있습니다. 우리의 경우에는 당연히 'data'이벤트 리스너가 있었지만 if (!ignoring) { ... }, 스트림을 배출 할 때 데이터를 처리하지 않도록 부울을 확인했습니다 . ignoring = true; readable.resume();
joeytwiddle

5
물론 이것은 스트림이 'end'어느 시점에 있을 것이라고 가정합니다 . 모든 스트림이 그렇게하는 것은 아닙니다! (예 까지나 일마다 초당 전송 스트림).
joeytwiddle

3

오래된 질문이지만 저도 답을 찾고 내 구현에 가장 적합한 질문을 찾았습니다. endclose이벤트가 모두 발생하므로 이것이 가장 깨끗한 솔루션이라고 생각합니다.

이것은 노드 4.4. * (작성 당시 안정적인 버전)에서 트릭을 수행합니다.

var input = fs.createReadStream('lines.txt');

input.on('data', function(data) {
   if (gotFirstLine) {
      this.end(); // Simple isn't it?
      console.log("Closed.");
   }
});

자세한 설명은 http://www.bennadel.com/blog/2692-you-have-to-explicitly-end-streams-after-pipes-break-in-node-js.htm을 참조하십시오.


2

이 코드는 트릭을 훌륭하게 수행합니다.

function closeReadStream(stream) {
    if (!stream) return;
    if (stream.close) stream.close();
    else if (stream.destroy) stream.destroy();
}

writeStream.end ()는 writeStream을 닫는 방법입니다.


1
.end ()가 이동 방법이라고 언급했지만 코드에서 close 및 destroy를 사용하고 end도 사용하지 않는 이유는 무엇입니까?
Lucas B

1
이 예제에서 readStream을 닫고 있습니다 ... writeStream-사용.end
g00dnatur3
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.