最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Node.js I/O流操作方法

 更新時間:2026年04月07日 09:03:41   作者:吳聲子夜歌  
文章主要介紹了Node.js中的流的概念、類型及使用方法,包括基本概念、類型、Buffer、可讀流、可寫流、雙工流和轉(zhuǎn)換流的創(chuàng)建、屬性、方法和事件,以及常見操作,感興趣的朋友跟隨小編一起看看吧

I/O流,即輸入(input)、輸出(output)流,它提供了一種向存儲設(shè)備寫入數(shù)據(jù)和從存儲設(shè)備讀取數(shù)據(jù)的方式,它是Node.js中執(zhí)行讀寫文件操作的一種非常重要的方式。

1、流簡介

1.1、流的基本概念

程序中的流是一個抽象概念,當(dāng)程序需要從某個數(shù)據(jù)源讀取數(shù)據(jù)時,就會開啟一個數(shù)據(jù)流,數(shù)據(jù)源可以是文件、內(nèi)存或者網(wǎng)絡(luò)等,而當(dāng)程序?qū)?shù)據(jù)寫入某個數(shù)據(jù)源時,也會開啟一個數(shù)據(jù)流,而數(shù)據(jù)源的目的地也可以是文件、內(nèi)存或者網(wǎng)絡(luò)等。

以文件流為例,當(dāng)需要讀取一個文件時,如果使用fs模塊的readFile()方法讀取,程序會將該文件的內(nèi)容視為一個整體,為其分配緩存區(qū)并一次性將內(nèi)容讀取到緩存區(qū)中,在這期間,Node.js將不能執(zhí)行任何其他處理,這就可能導(dǎo)致一個問題,即如果文件很大,會耗費(fèi)較多的時間。

如果使用文件流讀取文件,則可以將文件一部分一部分地讀取,這樣可以保證效率,并且不會占用太大的內(nèi)存。

1.1.1、流的基本類型

Node.js中的流有4種基本類型,分別如下。

  • Readable:可讀流。
  • Writable:可寫流。
  • Duplex:可讀可寫流(也稱雙工流)?。
  • Transform:轉(zhuǎn)換流,表示在讀寫過程中可以修改和變換數(shù)據(jù)的Duplex流。

1.1.2、流模塊的引用

使用Node.js中的流之前,首先要引用stream模塊,代碼如下:

const stream = require('stream');

1.2、Buffer

Buffer就是開辟的一塊內(nèi)存區(qū)域,Buffer的大小就是開辟的內(nèi)存區(qū)域的大小。在流中,Buffer的大小取決于傳入流構(gòu)造函數(shù)的highWaterMark選項(xiàng)參數(shù),該參數(shù)指定了字節(jié)總數(shù)或者對象總數(shù),當(dāng)可讀緩沖區(qū)的總大小達(dá)到highWaterMark指定的閾值時,流會暫時停止從數(shù)據(jù)源讀取數(shù)據(jù),直到當(dāng)前緩沖區(qū)的數(shù)據(jù)被釋放;如果要獲取緩沖區(qū)中存儲的數(shù)據(jù),需要使用writable.writableBuffer或readable.readableBuffer。

2、可讀流的使用

2.1、流的讀取模式與狀態(tài)

2.1.1、可讀流的讀取模式

可讀流有兩種讀取模式,即流動(flowing)模式和暫停(paused)模式。

所有的可讀流都是以暫停模式開始,當(dāng)流處于暫停模式時,可以通過read()方法從流中按需讀取數(shù)據(jù)。

流動模式指的是一旦開始讀取文件,會按照highWaterMark的值按次讀取,直到讀取完為止。當(dāng)流處于流動模式時,因?yàn)閿?shù)據(jù)是持續(xù)變化的,所以需要使用監(jiān)聽事件來處理它。

流的暫停模式和流動模式是可以互相切換的,如通過添加data事件、使用resume()方法或者pipe()方法等都可以將可讀流從暫停模式切換為流動模式;使用paused()方法或者unpipe()方法可以將可讀流從流動模式切換為暫停模式。

2.1.2、可讀流的狀態(tài)

在實(shí)際使用可讀流時,它一共有3種狀態(tài),即初始狀態(tài)(null)、流動狀態(tài)(true)和非流動狀態(tài)(false)。

當(dāng)流處于初始狀態(tài)(null)時,由于沒有數(shù)據(jù)使用者,所以流不會產(chǎn)生數(shù)據(jù),這時如果監(jiān)聽data事件、調(diào)用pipe()方法或resume()方法,都會將當(dāng)前狀態(tài)切換為流動狀態(tài)(true),這樣可讀流即可開始主動地產(chǎn)生數(shù)據(jù)并觸發(fā)事件。

如果調(diào)用pause()方法或者unpipe()方法,就會將可讀流的狀態(tài)切換為非流動狀態(tài)(false),這將暫停流,但不會暫停數(shù)據(jù)生成。此時,如果再為data事件設(shè)置監(jiān)聽器,就不會再將狀態(tài)切換為流動狀態(tài)(true)了。

2.2、可讀流的創(chuàng)建

Node.js中的可讀流使用stream模塊中的Readable類表示,因此可以直接使用下面代碼創(chuàng)建:

const readable = new stream.Readable();

另外,還可以使用fs模塊的createReadStream方法創(chuàng)建可讀流,語法格式如下:

fs.createReadStream(path[, options])
  • path:讀取文件的文件路徑,可以是字符串、緩沖區(qū)或網(wǎng)址。
  • options:讀取文件時的可選參數(shù),可選值如下。
    • flags:指定文件系統(tǒng)的權(quán)限,默認(rèn)為r。
    • encoding:編碼方式,默認(rèn)為null。
    • fd:文件描述符,默認(rèn)為null。
    • mode:設(shè)置文件模式,默認(rèn)為0o666。
    • autoClose:文件出錯或者結(jié)束時,是否自動關(guān)閉文件,默認(rèn)為true。
    • emitClose:流銷毀時,是否發(fā)送close事件,默認(rèn)為true。
    • start:指定開始讀取的位置。
    • end:指定結(jié)束讀取的位置。
    • highWaterMark:可讀取的閾值,一般設(shè)置在16~100KB范圍內(nèi)。
const fs = require("fs");
const read = fs.createReadStream("春夜喜雨.txt");

2.3、可讀流的屬性 方法及事件

可讀流提供了很多屬性、方法和事件,用來獲取可讀流信息、對可讀流進(jìn)行操作,以及監(jiān)聽可讀流的相應(yīng)操作,如下表:

常用屬性:

屬性說明
destroyed可讀流是否已銷毀,如果已經(jīng)調(diào)用了readable.destroyO方法,則該屬性值為true
readable可讀流是否被破壞、結(jié)束或者報錯
readableEncoding獲取可讀流的encoding屬性
readableEnded可讀流是否已經(jīng)沒有數(shù)據(jù),如果觸發(fā)了end事件,則該屬性值為rue
readableFlowing可讀流的當(dāng)前狀態(tài)
readableHighWaterMark構(gòu)造可讀流時傳入的high WaterMark的值
readableLength獲取準(zhǔn)備讀取的隊(duì)列中的字節(jié)數(shù)(或?qū)ο髷?shù))

常用方法:

方法說明
read([sizel)從流中讀取數(shù)據(jù)
setEncoding(encoding)設(shè)置從流中讀取的數(shù)據(jù)所使用的編碼
pause()暫停從可讀流對象發(fā)出的data事件
ispaused()獲取可讀流的當(dāng)前操作狀態(tài)
destroy()銷毀可讀流
resume()恢復(fù)從可讀流對象發(fā)出的data事件
pipe(destination[,options])把可讀流的輸出傳輸?shù)揭粋€由deatination參數(shù)指定的Writable流對象
unpipe([destinationl)分離附加的Writale流對象
filter(fn[,options])篩選流
forEach(fn[,options])迭代遍歷流

常用事件:

事件說明
close當(dāng)流或其數(shù)據(jù)源被關(guān)閉時,觸發(fā)該事件
data在流將數(shù)據(jù)塊傳送給使用者后觸發(fā)
end當(dāng)流中沒有數(shù)據(jù)可供使用時觸發(fā)
error當(dāng)流由于底層內(nèi)部故障而無法生成數(shù)據(jù)或嘗試推送無效數(shù)據(jù)塊時觸發(fā)
pause當(dāng)調(diào)用stream.pause().且readsFlowing不為false時觸發(fā)
readable當(dāng)有數(shù)據(jù)可從流中讀取時觸發(fā)
resume當(dāng)調(diào)用stream.resume().且readsFlowing不為true時觸發(fā)

觸發(fā)流事件同樣采用on()方法實(shí)現(xiàn),例如,下面代碼創(chuàng)建了一個可讀流,然后觸發(fā)其data事件:

const fs = require("fs")
let read = fs.createReadStream('春夜喜雨.txt')
read.on('data', (chunk)=>{
    console.log("讀取到的數(shù)據(jù):" + chunk.toString());
})
讀取到的數(shù)據(jù):  春夜喜雨
          杜甫
好雨知時節(jié),當(dāng)春乃發(fā)生。
隨風(fēng)潛入夜,潤物細(xì)無聲。
野徑云俱黑,江船火獨(dú)明。
曉看紅濕處,花重錦官城。

2.4、可讀流的常見操作

2.4.1、讀取數(shù)據(jù)

使用read()方法可以從流中讀取數(shù)據(jù),其語法格式如下:

對象名.read([size])
  • size:要讀取的數(shù)據(jù)的字節(jié)數(shù)。
  • 返回值:返回值可能為字符串、Buffer、null等。
const fs = require("fs");
const read = fs.createReadStream("春夜喜雨.txt", {encoding: 'utf-8'});
read.on('readable', ()=>{
     while (null !== (chunk = read.read(25))) {
          console.log(chunk.toString());
     }
});

2.4.2、設(shè)置編碼格式

可讀流讀取數(shù)據(jù)時,默認(rèn)情況下沒有設(shè)置字符編碼,流數(shù)據(jù)返回的是Buffer對象。如果設(shè)置了字符編碼,則流數(shù)據(jù)返回指定編碼的字符串。設(shè)置可讀流中數(shù)據(jù)的編碼格式需要使用setEncoding()方法,其語法格式如下:

對象名.setEncoding(encoding)
const fs = require("fs");
const read = fs.createReadStream("春夜喜雨.txt");
read.setEncoding("utf8")                       //設(shè)置編碼格式
read.on('readable', function () {
     while (null !== (chunk = read.read(25))) {
        //設(shè)置編碼格式后,此處不再需要使用toString()方法
        console.log(chunk);
     }                
});
        春夜喜雨
          杜甫
好雨知時節(jié),當(dāng)春乃發(fā)生。
隨風(fēng)潛入夜,潤物細(xì)無聲。
野徑云俱黑,江船火獨(dú)明。

2.4.3、 暫停與恢復(fù)流

pause()方法可以使流動模式的可讀流停止觸發(fā)data事件,并切換為非流動模式,其語法格式如下:

對象名.pause()

resume()方法可以恢復(fù)從可讀流對象發(fā)出的data事件,將可讀流切換為流動模式,其語法格式如下:

對象名.resume()

按行輸出故事內(nèi)容:

const fs = require('fs');
const read= fs.createReadStream("春夜喜雨.txt", {highWaterMark: 25});
read.setEncoding("utf8")                       //設(shè)置編碼格式
read.on('data', (chunk)=>{
     console.log(chunk.toString());
     read.pause();
     setTimeout(()=>{
          read.resume();
     }, 1000);
});
read.on("close",()=>{
     console.log("讀取完畢");
})

2.4.4、 獲取流的運(yùn)行狀態(tài)

對可讀流進(jìn)行操作時,可以使用ispaused()方法判斷流當(dāng)前的操作狀態(tài),該方法不需要參數(shù),返回結(jié)果為true或false,其語法格式如下:

對象名.ispaused()
const readable = new stream.Readable();
console.log(readable.ispaused());
readable.pause()
console.log(readable.ispaused());
false
true

ispaused()方法主要用于readable.pipe()底層的機(jī)制,大多數(shù)情況下不會直接使用該方法。

2.4.5、 銷毀流

使用destroy()方法可以銷毀可讀流,其語法格式如下:

對象名.destroy([error])

該方法中有一個可選參數(shù)error,用于在處理錯誤事件時發(fā)出錯誤。

const fs = require("fs")
const read = fs.createReadStream('春夜喜雨.txt')
read.setEncoding("utf8")
read.on('data', function (chunk) {
     console.log("讀取到的數(shù)據(jù):\n" + chunk.toString());
})
read.destroy()

上面代碼運(yùn)行結(jié)果為空,因?yàn)樽詈笠恍写a銷毀了可讀流read,可讀流在銷毀后,會將讀取的數(shù)據(jù)清空,因此,通常在程序可能出現(xiàn)異常時,才會在處理異常的過程中使用銷毀流方法。

2.4.6、 綁定可寫流至可讀流

readable.pipe()方法可以將可寫流綁定到可讀流,并將可讀流自動切換到流動模式,同時將可讀流的所有數(shù)據(jù)推送到綁定的可寫流。pipe()方法的語法格式如下:

可讀流對象名.pipe(destination[, options])
  • destination:要綁定到可讀流的可寫流對象。
  • options:保存管道選項(xiàng),通常為end參數(shù),其參數(shù)值為true,表示如果可讀流觸發(fā)end事件,可寫流也調(diào)用steam.end()結(jié)束寫入,如果設(shè)置end值為false,則目標(biāo)流就會保持打開。
  • 返回值:返回目標(biāo)可寫流。

pipe的含義為管道,比如要從A桶中向B桶中倒水,如果直接用A桶來倒水,那么水流可能會忽大忽小,而B桶中的水有可能因?yàn)橐绯龌蛘邅聿患笆褂枚速M(fèi),那么如何讓水不浪費(fèi)呢?這時就可以用一根水管連接A桶與B桶,這樣A桶中的水通過水管勻速地流向B桶,B桶中的水就可以及時使用而不會造成浪費(fèi)。流中的pipe也是如此,它是連接可讀流和可寫流的一條管道,可以實(shí)現(xiàn)讀取數(shù)據(jù)和寫入數(shù)據(jù)的一致性。這里需要說明的是,pipe()是可讀流的方法,只能將可寫流綁定到可讀流,反之則不可以。

通過將可寫流綁定至可讀流為文件追加內(nèi)容。

const fs = require("fs");
const read = fs.createReadStream('春夜喜雨.txt');                    //創(chuàng)建可讀流
const write = fs.createWriteStream('aaa.txt', {flags: "a"});  //創(chuàng)建可寫流
read.pipe(write);                                              //將可寫流綁定到可讀流
console.log("已完成")

2.4.7、 解綁可寫流

上文講解了使用可讀流的pipe()方法可以將可寫流綁定到可讀流,還可以通過可讀流的unpipe()方法將已經(jīng)綁定的可寫流進(jìn)行解綁,其語法格式如下:

可讀流對象名.unpipe([destination])

該方法中有一個可選參數(shù)destination,表示要解綁的可寫流,如果該參數(shù)省略,表示解綁所有的可寫流。

const fs = require("fs");
const read = fs.createReadStream('春夜喜雨.txt');                    //創(chuàng)建可讀流
const write = fs.createWriteStream('bbb.txt', {flags: "a"});  //創(chuàng)建可寫流
read.pipe(write);                                              //將可寫流綁定到可讀流
console.log("已綁定可寫流")
read.unpipe(write)                                             //解綁
console.log("已解綁可寫流")

上面代碼先為可讀流read綁定一個可寫流write,這時春夜喜雨.txt文件中的內(nèi)容都被追加到“bbb.txt”文件中,然后將write解綁,于是從“bbb.txt”文件中移除春夜喜雨.txt中的內(nèi)容,最終“涼州詞.txt”文件中的內(nèi)容將不會發(fā)生變化。

3、可寫流的使用

3.1、可寫流的創(chuàng)建

Node.js中的可寫流使用stream模塊中的Writable類表示,使用該類時,需要重寫其中的write()方法,因此要使用stream模塊中的Writable類創(chuàng)建可寫流,需要使用的代碼類似下面代碼:

const stream = require('stream');
const writable = new stream.Writable({
     write: function (chunk, encoding, next) {
          console.log(chunk.toString());
          next();
     }
});

另外,還可以使用fs模塊的createWriteStream()方法創(chuàng)建可寫流,語法格式如下:

fs.createWriteStream(path[, options])
  • path:寫入文件的文件路徑。
  • options:寫入文件時的可選參數(shù),可選值如下。
    • flags:指定文件系統(tǒng)的權(quán)限,默認(rèn)為w,如果要修改文件內(nèi)容,而不是替換,需要將該值設(shè)置為a。
    • encoding:編碼方式,默認(rèn)為null。
    • fd:文件描述符,默認(rèn)為null。
    • mode:設(shè)置文件模式,默認(rèn)為0o666。
    • autoClose:文件出錯或者結(jié)束時,是否自動關(guān)閉文件,默認(rèn)為true。
    • emitClose:流銷毀時,是否發(fā)送close事件,默認(rèn)為true。
    • start:指定開始寫入的位置。
    • highWaterMark:可寫入的閾值,一般設(shè)置在16~100KB范圍內(nèi)。
var fs = require("fs");
var write = fs.createWriteStream('demo.txt');  //創(chuàng)建可寫流

3.2、可寫流的屬性 方法及事件

可寫流提供了很多屬性、方法和事件,用來獲取可寫流信息、對可寫流進(jìn)行操作,以及監(jiān)聽可寫流的相應(yīng)操作,它們的說明分別如表所示。

常用屬性:

屬性說明
destroyed可寫流是否已銷毀,如果已經(jīng)調(diào)用了writable.destroy(),則為true
writable可寫流是否被破壞、報錯或結(jié)束
writableEnded可寫流是否已經(jīng)沒有數(shù)據(jù),如果在調(diào)用writable.end()之后,該值為rue
writableCorked獲取完全uncork流需要調(diào)用writable.uncork()的次數(shù)
writableFinished可寫流中的數(shù)據(jù)是否已傳輸完,在觸發(fā)finish事件之前需將其設(shè)置為true
writableHigh WaterMark返回構(gòu)造可寫流時傳入的high WaterMark的值
writableLength包含準(zhǔn)備寫入的隊(duì)列中的字節(jié)數(shù)(或?qū)ο螅?/td>
writableNeedDrain如果流的緩沖區(qū)已滿且流將發(fā)出drain,則為true

常用方法:

方法說明
write()寫入數(shù)據(jù)
end()通知可寫流對象寫入結(jié)束
setDefaultEncoding為可寫流設(shè)置默認(rèn)的編碼方式
end()關(guān)閉可寫流
destroy()銷毀可寫流
cork()強(qiáng)制把所有寫入的數(shù)據(jù)都緩沖到內(nèi)存中
uncork()將調(diào)用stream.cork0方法緩沖的所有數(shù)據(jù)輸出到目標(biāo)

常用事件:

事件說明
close當(dāng)可寫流或數(shù)據(jù)源被關(guān)閉時,觸發(fā)該事件
open創(chuàng)建可寫流的同時會打開文件,而打開文件就會觸發(fā)該事件
drain當(dāng)寫入緩沖區(qū)為空時觸發(fā)該事件
error寫入或管道數(shù)據(jù)發(fā)生錯誤時觸發(fā)該事件
finish調(diào)用stream.end()且緩沖區(qū)數(shù)據(jù)都已傳給底層系統(tǒng)之后觸發(fā)該事件
pipe當(dāng)在可讀流上調(diào)用stream.pipe()方法時會觸發(fā)該事件,并將此可寫流添加到其目標(biāo)集
unpipe在可讀流上調(diào)用stream.unpipeO方法時會觸發(fā)該事件,從其目標(biāo)集中移除此可寫流

3.3、可寫流的常見操作

3.3.1、寫入數(shù)據(jù)

使用write()方法可以向流中寫入數(shù)據(jù),其語法格式如下:

對象名.write( chunk[, encoding, callback])
  • chunk:要寫入的數(shù)據(jù),其值可以是字符串、緩沖區(qū)或數(shù)組等。
  • encoding:可選參數(shù),表示寫入數(shù)據(jù)時的編碼方式。
  • callback:可選參數(shù),是一個回調(diào)函數(shù),寫入數(shù)據(jù)完成后執(zhí)行。
const fs = require("fs")
let txt = "這首詩抓住了邊塞風(fēng)光景物的一些特點(diǎn),借其嚴(yán)寒春遲及胡笳聲聲來寫戰(zhàn)士們的心理活動,反映了邊關(guān)將士的生活狀"
    + "況。詩風(fēng)蒼涼悲壯,但并不低沉,以俠骨柔情為壯士之聲,這仍然是盛唐氣象的回響。"
//在文件原有內(nèi)容后面追加內(nèi)容,所以定義文件權(quán)限為“a”
let decr = fs.createWriteStream("涼州詞.txt", {flags: "a"})
decr.write("\n鑒賞:\n" + txt, "utf8")                     //寫入內(nèi)容

3.3.2、設(shè)置編碼方式

使用setDefaultEncoding()方法可以設(shè)置可寫流的默認(rèn)編碼方式,其語法格式如下:

對象名.setDefaultEncoding(encoding)
  • 參數(shù)encoding表示要設(shè)置的編碼方式。
const fs = require("fs")
const writeSteam = fs.createWriteStream("demo.txt")
writeSteam.setDefaultEncoding("utf8")              //設(shè)置編碼方式
writeSteam.write("測試數(shù)據(jù)")                       //寫入內(nèi)容

3.3.3、關(guān)閉流

寫入流的end()方法用來標(biāo)識已經(jīng)沒有需要寫入流中的數(shù)據(jù)了,因此通常用來關(guān)閉流,其語法格式如下:

對象名.end([chunk[, encoding]][, callback])
  • chunk:可選參數(shù),表示關(guān)閉流之前要寫入的數(shù)據(jù)。
  • encoding:如果chunk為字符串,那么encoding為編碼方式。
  • callback:流結(jié)束或者報錯時的回調(diào)函數(shù)。
const fs = require("fs")
const writeSteam = fs.createWriteStream("demo.txt")
writeSteam.setDefaultEncoding("utf8")              //設(shè)置編碼方式
writeSteam.write("測試數(shù)據(jù)")                       //寫入內(nèi)容
writeSteam.end("寫入完成")                         //關(guān)閉流
//writeSteam.write('繼續(xù)寫入');
測試數(shù)據(jù)
寫入完成

使用end()方法關(guān)閉流后,無法再向流中寫入數(shù)據(jù),否則將會產(chǎn)生異常,例如,去掉上面代碼中最后一行的注釋,再次運(yùn)行時,將會出現(xiàn)錯誤提示。

3.3.4、銷毀流

使用destroy()方法可以銷毀所創(chuàng)建的寫入流,并且流被銷毀后,無法再向流寫入數(shù)據(jù)。其語法格式如下:

對象名.destroy([error])
  • 參數(shù)error為可選參數(shù),表示使用error事件觸發(fā)的錯誤。
const fs = require("fs")
const writeSteam = fs.createWriteStream("demo.txt")
writeSteam.setDefaultEncoding("utf8")              //設(shè)置編碼方式
writeSteam.write("測試數(shù)據(jù)")                       //寫入內(nèi)容
writeSteam.destroy()                               //銷毀流

上面代碼運(yùn)行后,將會導(dǎo)致demo.txt文件中沒有任何數(shù)據(jù),因?yàn)殡m然第4行代碼中使用write()方法寫入了數(shù)據(jù),但由于緊接著銷毀了寫入流,這將導(dǎo)致使用該流執(zhí)行的任何操作都會失效。因此,在使用寫入流銷毀操作時,通常在異常處理中使用該操作。

3.3.5、將數(shù)據(jù)緩沖到內(nèi)存

使用寫入流的cork()方法可以強(qiáng)制把所有寫入的數(shù)據(jù)都緩沖到內(nèi)存中,它的主要目的是為了適應(yīng)將幾個數(shù)據(jù)快速連續(xù)地寫入流的情況。cork()方法不會立即將它們轉(zhuǎn)發(fā)到底層目標(biāo)處,而是緩沖所有數(shù)據(jù)塊,直到調(diào)用uncork()方法。cork()方法的語法格式如下:

對象名.cork()

當(dāng)使用uncork()方法或end()方法時,緩沖區(qū)數(shù)據(jù)將被刷新。

const stream = require('stream');
const writable = new stream.Writable({
     write: function (chunk, encoding, next) {
          console.log(chunk.toString());
          next();
     }
});
writable.write('天氣晴朗');
writable.cork();
writable.write('陽光明媚');
天氣晴朗

通過觀察上面結(jié)果,發(fā)現(xiàn)調(diào)用cork()方法后,接下來要輸出的內(nèi)容并沒有顯示。

3.3.6、輸出緩沖后的數(shù)據(jù)

前面介紹了cork()方法,用以強(qiáng)制把所有寫入的數(shù)據(jù)都緩沖到內(nèi)存中,而使用uncork()方法可以將調(diào)用cork()方法后緩沖的所有數(shù)據(jù)輸出到目標(biāo)處。uncork()方法的語法格式如下:

對象名.uncork()
const stream = require('stream');
const writable = new stream.Writable({
     write: function (chunk, encoding, next) {
          console.log(chunk.toString());
          next();
     }
});
writable.write('天氣晴朗');
writable.cork();
writable.write('陽光明媚');
writable.uncork();
天氣晴朗
陽光明媚

4、雙工流與轉(zhuǎn)換流

4.1、雙工流

雙工流Duplex可以實(shí)現(xiàn)流的可讀和可寫功能,即同時實(shí)現(xiàn)Readable和Writable。實(shí)現(xiàn)雙工流需要進(jìn)行以下3步。

  1. 繼承Duplex類。
  2. 實(shí)現(xiàn)_read()方法。
  3. 實(shí)現(xiàn)_write()方法。
const Duplex = require('stream').Duplex;
const myDuplex = new Duplex({
     _read(size) {
          // ...
     },
     _write(chunk, encoding, callback) {
          // ...
     }
});

示例:雙工流的使用

const stream = require('stream');
const duplexStream = stream.Duplex();
duplexStream._read = function () {
     this.push('讀取數(shù)據(jù)');
     this.push(null)
}
duplexStream._write = function (data, enc, next) {
     console.log(data.toString());
     next();
}
duplexStream.on('data', data => console.log("監(jiān)聽:" + data.toString()));
duplexStream.on('end', data => console.log('監(jiān)聽:' + '讀取完成'));
duplexStream.write('寫入數(shù)據(jù)');
duplexStream.end();
duplexStream.on('finish', data => console.log('監(jiān)聽:' + '寫入完成'));
寫入數(shù)據(jù)
監(jiān)聽:讀取數(shù)據(jù)
監(jiān)聽:寫入完成
監(jiān)聽:讀取完成

4.2、轉(zhuǎn)換流

轉(zhuǎn)換流Transform其實(shí)也是雙工流,它與Duplex的區(qū)別在于,Duplex雖然同時具備可讀流和可寫流的功能,但兩者是相對獨(dú)立的,而Transform中可讀流的數(shù)據(jù)會經(jīng)過一定的處理過程自動進(jìn)入可寫流。需要說明的是,從可讀流到可寫流,它們的數(shù)據(jù)量不一定相同。例如,常見的壓縮、解壓縮用的zlib就使用了轉(zhuǎn)換流,壓縮和解壓縮前后的數(shù)據(jù)量明顯不同。

實(shí)現(xiàn)轉(zhuǎn)換流需要進(jìn)行以下兩步:

  1. 繼承Transform類。
  2. 實(shí)現(xiàn)_transform()方法。_transform()方法用來接收數(shù)據(jù),并產(chǎn)生輸出(需要調(diào)用this.push(data),如果不調(diào)用,則接收數(shù)據(jù)但不輸出)?。當(dāng)數(shù)據(jù)處理完后,必須執(zhí)行callback(err, data)回調(diào)函數(shù),該函數(shù)中的第一個參數(shù)用于傳遞錯誤信息,第二個參數(shù)用來輸出數(shù)據(jù)(效果和this.push(data)相同)?,但參數(shù)可以省略。
const Stream = require('stream')
class TransformReverse extends stream.Transform {
     constructor() {                               //繼承構(gòu)造函數(shù)
          super()
     }
     _transform(data, encoding, callback) {
          this.push(data);
          callback();
     }
}

示例:轉(zhuǎn)換流的使用

const Stream = require('stream');
class TransformStream extends Stream.Transform {
     constructor() {
          super()
     }
     _transform(data, encoding, callback) {
          //將寫入的數(shù)據(jù)進(jìn)行反轉(zhuǎn)
          const res = data.toString().split('').reverse().join('');
          this.push(res)                                 //輸出反轉(zhuǎn)后的數(shù)據(jù)
          callback()
    }
}
var transformStream = new TransformStream();
transformStream.on('data', data => console.log(data.toString()))
transformStream.on('end', data => console.log('讀取完成'));
transformStream.write('寫入數(shù)據(jù)');
transformStream.end()
transformStream.on('finish', data => console.log('寫入完成'));
據(jù)數(shù)入寫
讀取完成
寫入完成

到此這篇關(guān)于Node.js I/O流操作方法的文章就介紹到這了,更多相關(guān)Node.js I/O流內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

蓬溪县| 股票| 北京市| 渭源县| 岑溪市| 松溪县| 漯河市| 公主岭市| 枣庄市| 铜山县| 上杭县| 霍林郭勒市| 乌海市| 桐乡市| 城固县| 广河县| 盱眙县| 香格里拉县| 民丰县| 扎赉特旗| 新疆| 呼伦贝尔市| 清河县| 玉树县| 义乌市| 石台县| 佛冈县| 渝北区| 商南县| 汤阴县| 泉州市| 中方县| 景泰县| 山阳县| 当涂县| 涡阳县| 武义县| 二手房| 昭苏县| 东安县| 南皮县|