stream 是乙個抽象的介面,node中有很多物件實現了這個介面,例如,對http伺服器發起請求的request物件就是乙個stream,還有process.studo(標準輸出)。
舉乙個讀取檔案的例子
使用fs.readfilesync同步讀取乙個檔案,程式會被阻塞,所有的資料都會被讀取到記憶體中,換用fs.readfile讀取檔案,程式不會被阻塞,但是所有的資料依舊會被一次性全部讀取到記憶體中
當處理大檔案壓縮,歸檔,**檔案和巨大的日誌檔案的時候,記憶體使用就成了問題,在這種情況下,流的優勢就體現出來了
流被設計成非同步的方式,相比將剩餘的檔案資料一次性讀進記憶體中,還是值得讀取到乙個緩衝區,期望的操作將會被執行,而且結果會被寫到輸出流
node中,stream有四種流型別:
readable-可讀操作
writeable-可寫操作
duplex-可讀寫操作
transform-操作被寫入資料,然後讀出結果
所有的stream物件都是eventemitter的例項,常用的事件有:
data-當有資料可讀時觸發。
end-沒有更多的資料可讀時觸發
error-在接收和寫入過程中發生錯誤時觸發
finish-所有資料已被寫入到底層系統時觸發
下面為大家介紹常用的流操作
從流中讀取資料
建立input.txt檔案,內容如下
建立main.js檔案,**如下
let fs=require("fs");
//建立可讀流
let rs=fs.createreadstream('input.txt');
let result=""
rs.on('data',(data)=>)rs.on("end",()=>)
rs.on('error',(err)=>)
複製**
以上**執行結果如下:
fs.createreadstream(path,[options])
可選引數options為乙個物件,可以有以下屬性
注:如果指定utf8編碼,highwatemark要大於3個位元組
寫入流建立main.js檔案,**如下:
let fs=require("fs");
//建立乙個可寫流,寫到檔案 output.txt中
let ws=fs.createwritestream("output.txt");
ws.write(data);//data需為buffer/string,返回值為布林值,系統快取區滿時為false,沒滿時為true
ws.end();
ws.on("finish",()=>)
ws.on("error",(err)=>)複製**
檢視output.txt檔案顯示
管道流
管道提供了乙個輸出流到輸入流的機制。通常我們用於從乙個流中獲取資料並將資料傳遞到另乙個流中。
如上面的所示,我們把檔案比作裝水的桶,而水就是檔案裡的內容,我們用管子(pipe)連線兩個桶使得水從乙個桶流入另乙個桶,這樣就慢慢的實現了大檔案的複製過程。
以下例項我們通過讀取乙個檔案的內容並將內容寫入到另乙個檔案中
將上面的input.txt 寫入到output.txt,**如下
let fs=require("fs");
let rs=fs.createreadstream("input.txt");
let ws=fs.createwritestream("output,txt");
rs.pipe(ws);複製**
成功將input.txt的內容複製到output.txt中
pipe的實現原理
let fs = require('fs');
let path = require('path');
let readstream = require('./readstream');
let writestream = require('./writestream');
let rs = new readstream(path.join(__dirname,'./1.txt'),);
let ws = new writestream(path.join(__dirname,'./2.txt'),);
rs.on('data',function(chunk)
});ws.on('drain',function
());複製**
鏈式流鏈式是通過連線輸出流到另乙個流並建立多個流操作鏈的機制,鏈式流一般用於管道操作,
接下來我們就是用鏈式流來壓縮和解壓縮檔案。
建立compress.js檔案,**如下:
let fs=require("fs");let zlib=require("zlib");//壓縮input.txt檔案為input.txt.gzfs.createreadstream('input.txt').pipe(zlib.creategzip())
.pipe(fs.createwritestream('input.txt.gz'));//等價於fs.createreadstream('input.txt').pipe(zlib.creategzip())zlib.creategzip().pipe(fs.createwritestream('input.txt.gz'));複製**
執行**後,我們可以看到當前目錄下生成了乙個input.txt的壓縮檔案input.txt.gz.
接下來,讓我們來解壓該檔案,建立decompress.js,**如下:
let fs=require("fs");
let zlib=require("zlib");
fs.createreadstream('input.txt.gz').pipe(zlib.creategunzip())
.pipe(fs.createwritestream('input.txt'))複製**
下面說一下可讀流簡單實現
let eventemitter = require('events');let fs = require('fs');class readstream extends eventemitter }) } read
() let howmuchtoread = this.end?math.min(this.highwatermark,this.end-this.pos+1)
:this.highwatermark; fs.read(this.fd,this.buffer,0,howmuchtoread,this.pos,(err,bytesread)=> if(this.flowing) }else }); } pipe(ws) }); ws.on('drain',()=>) } resume
() pause
() destroy
()); return; } this.emit('close'); // 銷毀 }; open
() return; } this.fd = fd; // 儲存檔案描述符 this.emit('open'); // 檔案開啟了 }); }}
複製**
簡單說說MPEG
mpeg 1 mpeg 2和mpeg 4。mpeg 3 原本目標是為高畫質晰度電視 hdtv 設計,隨後發現mpeg 2已足夠hdtv應用,故mpeg 3的研發便中止。音訊物件 video audio objects 的編碼 3d內容 低位元率編碼 low bitrate encoding 和數字版...
簡單說說委託
在c 中,大多時候,方法的引數是資料,但有時我們會想將 方法 作為引數,這時,我們就可以用委託。委託一般情況下會和事件一起使用,事件說白了也是特殊的乙個方法。先看個例子吧 有很多方法,比如求平方,求階乘 想讓使用者輸入值,求該值的平方,階乘 using system using system.col...
簡單說說Http
總結一下http的一些基礎知識 格式大部分分為 起始行 頭部 包體 注意格式中的空格 回車符 換行符 請求報文 請求方法 url 協議版本 請求頭部 請求包體 響應報文 協議版本 狀態碼 狀態碼描述 響應頭部 響應包體 請求方法包含get post put delete等方法,常用的有get和pos...