stream流 都是events.EventEmitter的一個實例,都可以來創建自定義事件(也就是說,流是一個事件的實例)
在nodejs中 對http的請求與響應都是用流來實現的,請求就是一個輸入的流,響應就是一個輸出的流
使用stream流,可以提高性能,前面說的讀寫文件,是一次性把文件放在內存中,這樣就不大合適了,而stream流,是將讀取的文件放在Buffer(緩存)中。就是一邊放,一邊處理,steam流有兩個好處,就是處理數據和提高性能。
下面來實現一個流:
var fs = require('fs'); var myReadStream = fs.createReadStream(__dirname+"/readMe.txt","utf8");//創建一個讀取流的實例 var data="";//創建一個變量來接收文件 myReadStream.on("data",function(chunk){//data是在接收數據的時候用的監聽函數 當文件很大時,是把文件分成很多Buffer來接收的 所以這個函數可能執行多次 data+=chunk; }) myReadStream.on("end",function(){//end是接收完畢后的監聽函數 console.log(data); })
上訴代碼,如果不設置編碼為utf8,data值將會為Buffer,看着是一串數字
當然,還可以另一種設置編碼的方式:
var myReadStream = fs.createReadStream(__dirname+"/readMe.txt");//創建一個讀取流的實例 myReadStream.setEncoding("utf8");//設置編碼 var data="";//創建一個變量來接收文件 myReadStream.on("data",function(chunk){//data是在接收數據的時候用的監聽函數 當文件很大時,是把文件分成很多Buffer來接收的 所以這個函數可能執行多次 data+=chunk; }) myReadStream.on("end",function(){//end是接收完畢后的監聽函數 console.log(data); })
在原來的基礎上寫一個寫入流:
var myReadStream = fs.createReadStream(__dirname+"/readMe.txt");//創建一個讀取流的實例 var myWriteStream = fs.createWriteStream(__dirname+"/writeMe.txt");//創建一個寫入流 myReadStream.setEncoding("utf8");//設置編碼 myReadStream.on("data",function(chunk){//data是在接收數據的時候用的監聽函數 當文件很大時,是把文件分成很多Buffer來接收的 所以這個函數可能執行多次 myWriteStream.write(chunk);//將讀取到的片段寫入,參數就是要寫入的內容 }) myReadStream.on("end",function(){//end是接收完畢后的監聽函數 })
寫入流 還有一種用法
var myWriteStream = fs.createWriteStream(__dirname+"/writeMe.txt");//創建一個寫入流 var writeData = "hello world"; myWriteStream.write(writeData);//寫入 myWriteStream.end();//寫入完之后調用end方法 (調用這個方法是 代表這個流結束了,如果不掉用這個流,這個流是結束不了的,finish方法不會觸發) myWriteStream.on("finish",function(){//加一個監聽函數,監聽擼結束后 console.log("finished"); })
管道的使用pipe
用管道來實現賦值文件會非常簡單:
var fs = require('fs'); var myReadStream = fs.createReadStream(__dirname+"/readMe.txt");//創建一個讀取流的實例 var myWriteStream = fs.createWriteStream(__dirname+"/writeMe.txt");//創建一個寫入流 myReadStream.pipe(myWriteStream);//使用管道 將讀取流和寫入流連接到一起
下面來上一個真實的代碼,讀取文件,加密,壓縮,然后寫入
var crypto = require("crypto");//用來加密 var fs = require("fs"); var zlib = require("zlib");//用來壓縮 var password = new Buffer(process.env.PASS || "password"); var encryptStream = crypto.createCipher('aes-256-cbc',password); var gzip = zlib.createGzip(); var readStream = fs.createReadStream(__dirname+"/readMe.txt"); var writeStream = fs.createWriteStream(__dirname+"/out.gz"); readStream//讀取 .pipe(encryptStream)//加密 .pipe(gzip)//壓縮 .pipe(writeStream)//寫入 .on("finish",function(){//寫入結束的回調 console.log("done"); })
下面將上面代碼壓縮出來的out.gz文件解壓,解密,然后輸出到終端
var crypto = require("crypto");//用來加密 var fs = require("fs"); var zlib = require("zlib");//用來壓縮 var password = new Buffer(process.env.PASS || "password"); var decryptStream = crypto.createDecipher('aes-256-cbc',password); var gzip = zlib.createGunzip();//解壓 var readStream = fs.createReadStream(__dirname+"/out.gz"); readStream//讀取 .pipe(gzip)//解壓 .pipe(decryptStream)//解密 .pipe(process.stdout)//輸出到終端中 標准輸出 .on("finish",function(){//解壓后的回調 console.log("done"); })
上面的代碼稍微更改一下,將解密,解壓出來的文件寫入到deOut.txt文件中
var crypto = require("crypto");//用來加密 var fs = require("fs"); var zlib = require("zlib");//用來壓縮 var password = new Buffer(process.env.PASS || "password"); var decryptStream = crypto.createDecipher('aes-256-cbc',password); var gzip = zlib.createGunzip();//解壓 var readStream = fs.createReadStream(__dirname+"/out.gz"); var writeStream = fs.createWriteStream(__dirname+"/deOut.txt"); readStream//讀取 .pipe(gzip)//解壓 .pipe(decryptStream)//解密 .pipe(writeStream)//將解密,解壓的文件寫入到deOut.txt文件中 .on("finish",function(){//解壓后的回調 console.log("done"); })
小知識:
process.stdout.write("哈哈");
可以在終端打印出指定內容