2016-07-19 7 views
3

스트리밍을 사용하면 한 번에 전체 파일을 읽는 것이 낫다는 것을 읽었습니다. node.js, 생각을 이해합니다.하지만 스트림을 사용하여 파일을 읽는 것이 아니라고 생각합니다. Java 및 C++에서 스트림을 사용하는 파일을 읽고 싶을 때 어떻게됩니까? 도 무엇입니까 fs.createReadStream(<somefile>);fs.readFile(<somefile>); 의 차이점은 모두 비동기입니다.파일 읽기와 스트리밍의 차이점은 무엇입니까?

+3

"전체 파일 읽기"는 전체 파일을 메모리에 저장하는 반면 "스트리밍"은 파일을 청크로 처리한다는 점이 다릅니다. –

+0

및 스트림은 다음 청크가 전달되는 시점을 알 수 없기 때문에 비동기 제어 흐름이 필요합니다. – ftor

+0

그래서 유일한 차이점은 스트림과 fs.readFile 메서드가 모두 비동기식 (비 블로킹)이기 때문에 '스트림 저장 메모리'입니다. @FrédéricHamidi –

답변

8

우선은 FILEREAD 완전히 방법을 버퍼링입니다 :

여기에 무슨 말인지 보여주는 두 조각입니다. 스트리밍은 부분 버퍼링 방식입니다.

이제는 무엇을 의미합니까?

readFileSync() 및 readFile()과 같이 완전히 버퍼링 된 함수 호출은 데이터를 하나의 큰 얼룩으로 표시합니다. 즉, 읽기가 수행 된 후 전체 데이터 집합이 동기식 또는 비동기식으로 반환됩니다. 이러한 완전히 버퍼링 된 방법을 사용하면 모든 데이터가 읽힐 때까지 기다려야하고 내부적으로 노드는 메모리에 모든 데이터를 저장할 충분한 메모리를 할당해야합니다. 문제가 될 수 있습니다 - 디스크에서 1GB 파일을 읽는 응용 프로그램을 상상해보십시오. 완전히 버퍼링 된 액세스만으로는 readFile과 readFileSync가 모두 모든 데이터를 포함하는 문자열을 반환하기 때문에 읽기를 위해 파일의 전체 내용을 저장하는 데 1GB의 메모리를 사용해야합니다.

부분적으로 버퍼 된 액세스 방법이 다릅니다. 그들은 데이터 입력을 이산 사건으로 취급하지 않고 오히려 데이터가 읽혀 지거나 쓰여질 때 발생하는 일련의 사건으로 취급합니다. 그것들은 디스크/네트워크/다른 I/O에서 읽혀지는 데이터를 액세스 할 수있게합니다. 부분적으로 버퍼 된 액세스 방법은 다릅니다. 그들은 데이터 입력을 이산 사건으로 취급하지 않고 오히려 데이터가 읽혀 지거나 쓰여질 때 발생하는 일련의 사건으로 취급합니다. 그들은 우리가 디스크/네트워크/다른 I/O로부터 읽혀질 때 데이터에 접근 할 수있게 해줍니다.

Streams는 버퍼를 사용하여 데이터의 더 작은 부분을 반환하고 새 데이터를 처리 할 수있을 때 콜백을 트리거합니다.

스트림은 EventEmitters입니다.예를 들어 1GB 파일을 어떤 방식 으로든 한 번 처리해야하는 경우 스트림을 사용하고 읽을 때 데이터를 처리 할 수 ​​있습니다. 메모리에서 모든 데이터를 일부 버퍼에 보관할 필요가 없기 때문에이 방법이 유용합니다. 처리 후 더 이상이 종류의 응용 프로그램을 위해 메모리에 데이터를 보관할 필요가 없습니다.

노드 스트림 인터페이스는 읽기 가능 스트림과 쓰기 가능 스트림의 두 부분으로 구성됩니다. 일부 스트림은 읽고 쓸 수 있습니다.

+1

_since readFile과 readFileSync는 모두 data_ - wrong를 포함하는 문자열을 반환합니다. 명시 적으로 인코딩을 지정하지 않으면 기본적으로 'Buffer' 객체를 반환합니다. –

7

그래서 차이점은 무엇입니까 ?? 또한 fs.createReadStream(<somefile>);fs.readFile(<somefile>);의 차이점은 모두 비동기입니다.

음 옆 fs.createReadStream() 직접 stream 객체를 반환하고, fs.readFile()는 두 번째 인수에 콜백 함수를 기대하고 있다는 사실에서, 또 다른 큰 차이가 있습니다.

예 둘 다 비동기이지만, 전체 파일이 메모리에 버퍼링 될 때까지 fs.readFile()이 데이터를 제공하지 않는다는 사실은 변경되지 않습니다. 이것은 서버 응답을 통해 데이터를 다시 중계 할 때 메모리 효율이 훨씬 낮고 속도가 느립니다. fs.createReadStream()으로 pipe()stream 개체를 서버의 response 개체에 직접 연결할 수 있습니다. 즉, 클라이언트가 파일이 500MB 인 경우에도 즉시 데이터를받을 수 있습니다.

뿐만 아니라 한 번에 한 파일 씩 처리하여 메모리 효율성을 향상시킬 수도 있습니다. 즉, 한 번에 모두가 아니라 한 번에 몇 킬로바이트에 불과한 file 내용을 메모리에 버퍼하면됩니다.

const fs = require('fs'); 
const http = require('http'); 

// using readFile() 
http.createServer(function (req, res) { 
    // let's pretend this is a huge 500MB zip file 
    fs.readFile('some/file/path.zip', function (err, data) { 
     // entire file must be buffered in memory to data, which could be very slow 
     // entire chunk is sent at once, no streaming here 
     res.write(data); 
     res.end(); 
    }); 
}); 

// using createReadStream() 
http.createServer(function (req, res) { 
    // processes the large file in chunks 
    // sending them to client as soon as they're ready 
    fs.createReadStream('some/file/path.zip').pipe(res); 
    // this is more memory-efficient and responsive 
});