<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        NodeJS 中Stream 的基本使用

        來源:懂視網 責編:小采 時間:2020-11-27 22:10:48
        文檔

        NodeJS 中Stream 的基本使用

        NodeJS 中Stream 的基本使用:在 NodeJS 中,我們對文件的操作需要依賴核心模塊 fs , fs 中有很基本 API 可以幫助我們讀寫占用內存較小的文件,如果是大文件或內存不確定也可以通過 open 、 read 、 write 、 close 等方法對文件進行操作,但是這樣操作文件每一個步驟都要關心,非常繁瑣
        推薦度:
        導讀NodeJS 中Stream 的基本使用:在 NodeJS 中,我們對文件的操作需要依賴核心模塊 fs , fs 中有很基本 API 可以幫助我們讀寫占用內存較小的文件,如果是大文件或內存不確定也可以通過 open 、 read 、 write 、 close 等方法對文件進行操作,但是這樣操作文件每一個步驟都要關心,非常繁瑣

        在 NodeJS 中,我們對文件的操作需要依賴核心模塊 fs , fs 中有很基本 API 可以幫助我們讀寫占用內存較小的文件,如果是大文件或內存不確定也可以通過 open 、 read 、 write 、 close 等方法對文件進行操作,但是這樣操作文件每一個步驟都要關心,非常繁瑣, fs 中提供了可讀流和可寫流,讓我們通過流來操作文件,方便我們對文件的讀取和寫入。
        可讀流

        1、createReadStream 創建可讀流

        createReadStream 方法有兩個參數,第一個參數是讀取文件的路徑,第二個參數為 options 選項,其中有八個參數:

        r
        null
        null
        0o666
        true
        64 * 1024

        createReadStream 的返回值為 fs.ReadStream 對象,讀取文件的數據在不指定 encoding 時,默認為 Buffer。

        let fs = require("fs");
        // 創建可讀流,讀取 1.txt 文件
        let rs = fs.creatReadStream("1.txt", {
         start: 0,
         end: 3,
         highWaterMark: 2
        });

        在創建可讀流后默認是不會讀取文件內容的,讀取文件時,可讀流有兩種狀態,暫停狀態和流動狀態。

        注意:本篇的可寫流為流動模式,流動模式中有暫停狀態和流動狀態,而不是暫停模式,暫停模式是另一種可讀流 readable 。

        2、流動狀態

        流動狀態的意思是,一旦開始讀取文件,會按照 highWaterMark 的值一次一次讀取,直到讀完為止,就像一個打開的水龍頭,水不斷的流出,直到流干,需要通過監聽 data 事件觸發。

        假如現在 1.txt 文件中的內容為 0~9 十個數字,我們現在創建可讀流并用流動狀態讀取。

        let fs = require("fs");
        let rs = fs.createReadStream("1.txt", {
         start: 0,
         end: 3,
         highWaterMark: 2
        });
        // 讀取文件
        rs.on("data", data => {
         console.log(data);
        });
        // 監聽讀取結束
        rs.on("end", () => {
         console.log("讀完了");
        });
        // <Buffer 30 31>
        // <Buffer 32 33>
        // 讀完了

        在上面代碼中,返回的 rs 對象監聽了兩個事件:

        data:每次讀取 highWaterMark 個字節,觸發一次 data 事件,直到讀取完成,回調的參數為每次讀取的 Buffer;

        end:當讀取完成時觸發并執行回調函數。

        我們希望最后讀到的結果是完整的,所以我們需要把每一次讀到的結果在 data 事件觸發時進行拼接,以前我們可能使用下面這種方式。

        let fs = require("fs");
        let rs = fs.createReadStream("1.txt", {
         start: 0,
         end: 3,
         highWaterMark: 2
        });
        let str = "";
        rs.on("data", data => {
         str += data;
        });
        rs.on("end", () => {
         console.log(str);
        });
        // 0123

        在上面代碼中如果讀取的文件內容是中文,每次讀取的 highWaterMark 為兩個字節,不能組成一個完整的漢字,在每次讀取時進行 += 操作會默認調用 toString 方法,這樣會導致最后讀取的結果是亂碼。

        在以后通過流操作文件時,大部分情況下都是在操作 Buffer,所以應該用下面這種方式來獲取最后讀取到的結果。

        let fs = require("fs");
        let rs = fs.createReadStream("1.txt", {
         start: 0,
         end: 3,
         highWaterMark: 2
        });
        // 存儲每次讀取回來的 Buffer
        let bufArr = [];
        rs.on("data", data => {
         bufArr.push(data);
        });
        rs.on("end", () => {
         console.log(Buffer.concat(bufArr).toString());
        });
        // 0123

        3、暫停狀態

        在流動狀態中,一旦開始讀取文件,會不斷的觸發 data 事件,直到讀完,暫停狀態是我們每讀取一次就直接暫停,不再繼續讀取,即不再觸發 data 事件,除非我們主動控制繼續讀取,就像水龍頭打開放水一次后馬上關上水龍頭,下次使用時再打開。

        類似于開關水龍頭的動作,也就是暫停和恢復讀取的動作,在可讀流返回的 rs 對象上有兩個對應的方法, pause 和 resume 。

        在下面的場景中我們把創建可讀流的結尾位置更改成 9 ,在每次讀兩個字節并暫停一秒后恢復讀取,直到讀完 0~9 十個數字。

        let fs = require("fs");
        let rs = fs.createReadStream("1.txt", {
         start: 0,
         end: 9,
         hithWaterMark: 2
        });
        let bufArr = [];
        rs.on("data", data => {
         bufArr.push(data);
         rs.pause(); // 暫停讀取
         console.log("暫停", new Date());
         setTimeout(() => {
         rs.resume(); // 恢復讀取
         }, 1000)
        });
        rs.on("end", () => {
         console.log(Buffer.concat(bufArr).toString());
        });
        // 暫停 2018-07-03T23:52:52.436Z
        // 暫停 2018-07-03T23:52:53.439Z
        // 暫停 2018-07-03T23:52:54.440Z
        // 暫停 2018-07-03T23:52:55.442Z
        // 暫停 2018-07-03T23:52:56.443Z
        // 0123456789

        4、錯誤監聽

        在通過可讀流讀取文件時都是異步讀取,在異步讀取中如果遇到錯誤也可以通過異步監聽到,可讀流返回值 rs 對象可以通過 error 事件來監聽錯誤,在讀取文件出錯時觸發回調函數,回調函數參數為 err ,即錯誤對象。

        let fs = require("fs");
        // 讀取一個不存在的文件
        let rs = fs.createReadStream("xxx.js", {
         highWarterMark: 2
        });
        let bufArr = [];
        rs.on("data", data => {
         bufArr.push(data);
        });
        rs.on("err", err => {
         console.log(err);
        });
        rs.on("end", () => {
         console.log(Buffer.concat(bufArr).toString());
        });
        // { Error: ENOENT: no such file or directory, open '......xxx.js' ......}

        5、打開和關閉文件的監聽

        流的適用性非常廣,不只是文件讀寫,也可以用在 http 中數據的請求和響應上,但是在針對文件讀取返回的 rs 上有兩個專有的事件用來監聽文件的打開與關閉。

        open 事件用來監聽文件的打開,回調函數在打開文件后執行, close 事件用來監聽文件的關閉,如果創建的可讀流的 autoClose 為 true ,在自動關閉文件時觸發,回調函數在關閉文件后執行。

        let fs = require("fs");
        let rs = fs.createReadStream("1.txt", {
         start: 0,
         end: 3,
         highWaterMark: 2
        });
        rs.on("open", () => {
         console.log("open");
        });
        rs.on("close", () => {
         console.log("close");
        });
        // open

        在上面代碼我們看出只要創建了可讀流就會打開文件觸發 open 事件,因為默認為暫停狀態,沒有對文件進行讀取,所以不會關閉文件,即不會觸發 close 事件。

        let fs = require("fs");
        let rs = fs.createReadStream("1.txt", {
         start: 0,
         end: 3,
         hithWaterMark: 2
        });
        rs.on("open", () => {
         console.log("open");
        });
        rs.on("data", data => {
         console.log(data);
        });
        rs.on("end", () => {
         console.log("end");
        });
        rs.on("close", () => {
         console.log("close");
        });
        // open
        // <Buffer 30 31>
        // <Buffer 32 33>
        // end
        // close

        從上面例子執行的打印結果可以看出只有開始讀取文件并讀完后,才會關閉文件并觸發 close 事件, end 事件的觸發要早于 close 。

        可寫流

        1、createWriteStream 創建可寫流

        createWriteStream 方法有兩個參數,第一個參數是讀取文件的路徑,第二個參數為 options 選項,其中有七個參數:

        w
        utf8
        null
        0o666
        true
        16 * 1024
        createWriteStream 返回值為 fs.WriteStream 對象,第一次寫入時會真的寫入文件中,繼續寫入,會寫入到緩存中。
        let fs = require("fs");
        // 創建可寫流,寫入 2.txt 文件
        let ws = fs.createWriteStream("2.txt", {
         start: 0,
         highWaterMark: 3
        });

        2、可寫流的 write 方法

        在可寫流中將內容寫入文件需要使用 ws 的 write 方法,參數為寫入的內容,返回值是一個布爾值,代表 highWaterMark 的值是否足夠當前的寫入,如果足夠,返回 true ,否則返回 false ,換種說法就是寫入內容的長度是否超出了 highWaterMark ,超出返回 false 。

        let fs = require("fs");
        let ws = fs.createWriteSteam("2.txt", {
         start: 0,
         highWaterMark: 3
        });
        let flag1 = ws.write("1");
        console.log(flag1);
        let flag2 = ws.write("2");
        console.log(flag2);
        let flag3 = ws.write("3");
        console.log(flag3);
        // true
        // true
        // false

        寫入不存在的文件時會自動創建文件,如果 start 的值不是 0 ,在寫入不存在的文件時默認找不到寫入的位置。

        3、可寫流的 drain 事件

        drain 意為 “吸干”,當前寫入的內容已經大于等于了 highWaterMark ,會觸發 drain 事件,當內容全部從緩存寫入文件后,會執行回調函數。

        let fs = require("fs");
        let ws = fs.createWriteStream("2.txt", {
         start: 0,
         highWaterMark: 3
        });
        let flag1 = ws.write("1");
        console.log(flag1);
        let flag2 = ws.write("2");
        console.log(flag2);
        let flag3 = ws.write("3");
        console.log(flag3);
        ws.on("drain", () => {
         console.log("吸干");
        });
        // true
        // true
        // false

        4、可寫流的 end 方法

        end 方法傳入的參數為最后寫入的內容, end 會將緩存未寫入的內容清空寫入文件,并關閉文件。

        let fs = require("fs");
        let ws = fs.createWriteStream("2.txt", {
         start: 0,
         highWaterMark: 3
        });
        let flag1 = ws.write("1");
        console.log(flag1);
        let flag2 = ws.write("2");
        console.log(flag2);
        let flag3 = ws.write("3");
        console.log(flag3);
        ws.on("drain", () => {
         console.log("吸干");
        });
        ws.end("寫完了");
        // true
        // true
        // false

        在調用 end 方法后,即使再次寫入的值超出了 highWaterMark 也不會再觸發 drain 事件了,此時打開 2.txt 后發現文件中的內容為 "123寫完了"。

        let fs = require("fs");
        let ws = fs.createWriteStream("2.txt", {
         start: 0,
         highWaterMark: 3
        });
        ws.write("1");
        ws.end("寫完了");
        ws.write("2");
        // Error [ERR_STREAM_WRITE_AFTER_END]: write after end...

        在調用 end 方法后,不可以再調用 write 方法寫入,否則會報一個很常見的錯誤 write after end ,文件原有內容會被清空,而且不會被寫入新內容。

        可寫流與可讀流混合使用

        可寫流和可讀流一般配合來使用,讀來的內容如果超出了可寫流的 highWaterMark ,則調用可讀流的 pause 暫停讀取,等待內存中的內容寫入文件,未寫入的內容小于 highWaterMark 時,調用可寫流的 resume 恢復讀取,創建可寫流返回值的 rs 上的 pipe 方法是專門用來連接可讀流和可寫流的,可以將一個文件讀來的內容通過流寫到另一個文件中。

        let fs = require("pipe");
        // 創建可讀流和可寫流
        let rs = fs.createReadStream("1.txt", {
         highWaterMark: 3
        });
        let ws = fs.createWriteStream("2.txt", {
         highWaterMark: 2
        });
        // 將 1.txt 的內容通過流寫入 2.txt 中
        rs.pipe(ws);

        通過上面的這種類似于管道的方式,將一個流從一個文件輸送到了另一個文件中,而且會根據讀流和寫流的 highWaterMark 自由的控制寫入的 “節奏”,不用擔心內存的消耗。

        總結

        以上所述是小編給大家介紹的NodeJS 中Stream 的基本使用,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        NodeJS 中Stream 的基本使用

        NodeJS 中Stream 的基本使用:在 NodeJS 中,我們對文件的操作需要依賴核心模塊 fs , fs 中有很基本 API 可以幫助我們讀寫占用內存較小的文件,如果是大文件或內存不確定也可以通過 open 、 read 、 write 、 close 等方法對文件進行操作,但是這樣操作文件每一個步驟都要關心,非常繁瑣
        推薦度:
        標簽: 使用 的操作 基本
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 国产成人免费网站| 6080午夜一级毛片免费看6080夜福利 | 亚洲av中文无码乱人伦在线r▽| 国产亚洲色婷婷久久99精品| 亚洲最大在线观看| 色窝窝亚洲av网| 成人无码WWW免费视频| 97国产免费全部免费观看| 亚洲日本中文字幕天堂网| 亚洲a在线视频视频| 亚洲AV无码AV日韩AV网站| 777爽死你无码免费看一二区| 亚洲成AV人在线观看网址| 久久亚洲国产视频| 免费观看国产网址你懂的| 亚洲成AV人片在线播放无码| 精品亚洲国产成人av| 亚洲第一页日韩专区| 香蕉免费在线视频| 日本一道一区二区免费看| 亚洲v高清理论电影| 97国产免费全部免费观看| 亚洲AV色无码乱码在线观看| 不卡精品国产_亚洲人成在线| 国产成人综合久久精品亚洲| 免费阿v网站在线观看g| 亚洲AV日韩AV永久无码绿巨人| 永久免费在线观看视频| 亚洲精华国产精华精华液| 一个人免费观看www视频在线| 国产精品久久久久久亚洲影视| 国产亚洲精品线观看动态图| 曰批全过程免费视频网址| 337P日本欧洲亚洲大胆艺术图| 国产亚洲视频在线播放| 免费一级做a爰片久久毛片潮| 免费视频中文字幕| 自拍偷区亚洲国内自拍| 国产免费久久精品99re丫y| 无码免费又爽又高潮喷水的视频 | 全黄大全大色全免费大片|