一、什么是Stream(流)
流(stream)在 Node.js 中是處理流數(shù)據(jù)的抽象接口(abstract interface)。 stream 模塊提供了基礎的API。使用這些API可以很容易地來構建實現(xiàn)流接口的對象。例如, HTTP 請求 和 process.stdout 就都是流的實例。
流可以是可讀的、可寫的,或是可讀寫的。注意,所有的流都是 EventEmitter 的實例。
二、流的類型
Node.js 中有四種基本的流類型:
Readable - 可讀的流 (例如 fs.createReadStream())。 Writable - 可寫的流 (例如 fs.createWriteStream())。 Duplex - 可讀寫的流(雙工流) (例如 net.Socket)。 Transform - 在讀寫過程中可以修改和變換數(shù)據(jù)的 Duplex 流 (例如 zlib.createDeflate())。var Stream = require('stream') //stream 模塊引入方式var Readable = Stream.Readable //可讀的流var Writable = Stream.Writable //可寫的流var Duplex = Stream.Duplex //可讀寫的流var Transform = Stream.Transform //在讀寫過程中可以修改和變換數(shù)據(jù)的 Duplex 流Node.js中關于流的操作被封裝到了Stream模塊中,這個模塊也被多個核心模塊所引用。例如在fs.createReadStream()和fs.createWriteStream()的源碼實現(xiàn)里,都調用了Stream模塊提供的抽象接口來實現(xiàn)對流數(shù)據(jù)的操作。
三、為什么使用Stream?
我們通過兩個例子,了解一下為什么要使用Stream。
Exp1:
下面是一個讀取文件內容的例子:
const fs = require('fs')fs.readFile(file, function (err, content) { //讀出來的content是Buffer console.log(content) console.log(content.toString())})但如果文件內容較大,譬如在500M時,執(zhí)行上述代碼的輸出為:
<Buffer 64 74 09 75 61 09 63 6f 75 6e 74 0a 0a 64 74 09 75 61 09 63 6f 75 6e 74 0a 32 30 31 35 31 32 30 38 09 4d 6f 7a 69 6c 6c 61 2f 35 2e 30 20 28 63 6f 6d ... >buffer.js:382 throw new Error('toString failed'); ^Error: toString failed at Buffer.toString (buffer.js:382:11)報錯的原因是content這個Buffer對象的長度過大,導致toString方法失敗。
可見,這種一次獲取全部內容的做法,不適合操作大文件。
可以考慮使用流來讀取文件內容。
var fs = require('fs')fs.createReadStream(bigFile).pipe(process.stdout) fs.createReadStream創(chuàng)建一個可讀流,連接了源頭(上游,文件)和消耗方(下游,標準輸出)。
執(zhí)行上面代碼時,流會逐次調用fs.read(ReadStream這個類的源碼里有一個_read方法,這個_read方法在內部調用了fs.read來實現(xiàn)對文件的讀取),將文件中的內容分批取出傳給下游。
在文件看來,它的內容被分塊地連續(xù)取走了。
在下游看來,它收到的是一個先后到達的數(shù)據(jù)序列。
新聞熱點
疑難解答
圖片精選