在學(xué)習(xí)node的過(guò)程中,對(duì)于流的概念一直不是很理解,通過(guò)查閱一些資料,現(xiàn)在將自己對(duì)流的一些理解進(jìn)行總結(jié)一下。
一.流的理解
首先我們必須知道什么是流,很多書(shū)中只是提到使用流讀寫(xiě)文件怎么怎么方便,卻不提流到底是什么?在說(shuō)流之前我們先說(shuō)一下流數(shù)據(jù):
流數(shù)據(jù):就是字節(jié)數(shù)據(jù),在應(yīng)用程序中各種對(duì)象之間交換與傳輸數(shù)據(jù)的時(shí)候,總是先將該對(duì)象中所包含的數(shù)據(jù)轉(zhuǎn)化為字節(jié)數(shù)據(jù)也就是流數(shù)據(jù)。再通過(guò)流的傳輸,到達(dá)目的對(duì)象后,再將流數(shù)據(jù)轉(zhuǎn)化為該對(duì)象中可以使用的數(shù)據(jù)。
從上面可知,流就是用來(lái)傳輸流數(shù)據(jù)的,它是一種傳輸手段
流:在一個(gè)應(yīng)用程序中,流是一組有序的,有起點(diǎn)和終點(diǎn)的字節(jié)數(shù)據(jù)(流數(shù)據(jù))的傳輸手段
二,能夠使用流的對(duì)象
從流的概念中我們可以知道流是用來(lái)傳輸流數(shù)據(jù)的,也就是說(shuō)我們需要把其他的對(duì)象數(shù)據(jù)轉(zhuǎn)化為流數(shù)據(jù)。
在Node中,使用了各種實(shí)現(xiàn)了stream.Readable接口的對(duì)象讀取流。也就是說(shuō)只有這些對(duì)象才能夠讀取流。
Node.js中可以讀取數(shù)據(jù)流的對(duì)象,列表如下:
| 對(duì)象 | 描述 |
|---|---|
| fs.ReadStream | 用于讀取文件 |
| http.IncomingMesage | 代表客戶端請(qǐng)求或服務(wù)端響應(yīng) |
| net.Socket | 代表一個(gè)socket端口對(duì)象 |
| child.stdout | 用于創(chuàng)建子進(jìn)程的標(biāo)準(zhǔn)輸出流 |
| child.stderr | 用于創(chuàng)建子進(jìn)程的標(biāo)準(zhǔn)錯(cuò)誤輸出流 |
| process.stdin | 用于創(chuàng)建進(jìn)程的標(biāo)準(zhǔn)輸入流 |
| Gzip | 用于實(shí)現(xiàn)數(shù)據(jù)壓縮 |
上面這些讀取數(shù)據(jù)的對(duì)象將會(huì)觸發(fā)的事件
| 事件名 | 描述 |
|---|---|
| readable | 當(dāng)可以從流中讀取數(shù)據(jù)時(shí)觸發(fā) |
| data | 當(dāng)讀取到來(lái)自文件,客戶端,服務(wù)器端等對(duì)象的新的數(shù)據(jù)時(shí)觸發(fā) |
| end | 代表一個(gè)socket端口對(duì)象 |
| child.stdout | 當(dāng)讀取完所有的事件時(shí)觸發(fā),該事件的觸發(fā)意味著data事件將不再被觸發(fā) |
| err | 當(dāng)讀取數(shù)據(jù)的過(guò)程中產(chǎn)生錯(cuò)誤時(shí)觸發(fā) |
| close | 當(dāng)用于讀取數(shù)據(jù)的對(duì)象被關(guān)閉時(shí)觸發(fā),并非所有用于讀取流數(shù)據(jù)的對(duì)象都會(huì)觸發(fā)該事件 |
上面這些讀取數(shù)據(jù)的對(duì)象所擁有的方法
在對(duì)象讀取流的過(guò)程中,對(duì)象還擁有一些方法,可以對(duì)流進(jìn)行一些操作,比如指定編碼,指定流的傳輸目的地等。列表如下:
| 方法名 | 描述 |
|---|---|
| read | 用于讀取數(shù)據(jù) |
| setEncoding | 用于指定用什么編碼方式讀取數(shù)據(jù) |
| pause | 用于通知對(duì)象停止觸發(fā)data事件 |
| resume | 用于通知對(duì)象恢復(fù)觸發(fā)data事件 |
| pipe | 用于設(shè)置一個(gè)數(shù)據(jù)通道,然后取出所有流數(shù)據(jù)并將其輸出到通道另一端所指向的目標(biāo)對(duì)象中 |
| unpipe | 用于取消pipe設(shè)置的通道 |
接下來(lái)使用fs模塊中的createReadStream方法創(chuàng)建一個(gè)將文件讀取為流數(shù)據(jù)的ReadStream對(duì)象,介紹一下流數(shù)據(jù)的讀取。示例代碼如下:
const fs = require('fs');
let file = fs.createReadStream('./data.txt');
// console.log(file); //得到的是一個(gè)ReadStream對(duì)象
//對(duì)象在讀取文件時(shí),需要先打開(kāi)文件,打開(kāi)文件會(huì)觸發(fā)open事件
file.on('open',function(fd){
console.log('開(kāi)始讀取文件');
// console.log(fd);
});
//對(duì)象觸發(fā)data事件,讀取數(shù)據(jù)
file.on('data',function(data){
console.log('讀取到數(shù)據(jù)');
console.log(data.toString());
});
//讀取文件完畢,觸發(fā)end事件
file.on('end',function(){
console.log('文件讀取完畢');
});
//關(guān)閉文件,觸發(fā)close事件
file.on('close',function(){
console.log('關(guān)閉文件')
});
file.on('error',function(err){
console.log(err)
});
上面介紹了Node.js中用于讀取流的對(duì)象,以及在讀取過(guò)程中,對(duì)象可能觸發(fā)的事件以及調(diào)用的方法。下面介紹Node.js中用于寫(xiě)入流的對(duì)象,以及在寫(xiě)入過(guò)程中,這些對(duì)象可能觸發(fā)的事件和調(diào)用的方法。
在Node.js中,使用各種實(shí)現(xiàn)了stream.Writable接口的對(duì)象來(lái)將流數(shù)據(jù)寫(xiě)入到對(duì)象中,所有這些對(duì)象都是繼承了EventEmitter類的實(shí)例,在寫(xiě)入數(shù)據(jù)的過(guò)程中,將可能觸發(fā)各種事件
各種用于寫(xiě)入流數(shù)據(jù)的對(duì)象,如下表所示:
| 對(duì)象 | 描述 |
|---|---|
| fs.WriteStream | 用于寫(xiě)入文件 |
| http.ClientRequest | 用于寫(xiě)入http客戶端請(qǐng)求數(shù)據(jù) |
| http.ServerResponse | 用于寫(xiě)入http服務(wù)端響應(yīng)數(shù)據(jù) |
| net.Socket | 代表一個(gè)socket端口對(duì)象 |
| child.stdin | 用于創(chuàng)建子進(jìn)程的標(biāo)準(zhǔn)輸入流 |
| process.stderr | 用于創(chuàng)建進(jìn)程的標(biāo)準(zhǔn)錯(cuò)誤輸出流 |
| process.stdout | 用于創(chuàng)建進(jìn)程的標(biāo)準(zhǔn)輸出流 |
| Gunzip | 用于解壓數(shù)據(jù) |
這些對(duì)象將有可能觸發(fā)的事件如下表所示:
| 事件名 | 描述 |
|---|---|
| drain | 當(dāng)用于寫(xiě)入數(shù)據(jù)的write方法返回false之后觸發(fā) |
| finish | 當(dāng)end方法被調(diào)用且數(shù)據(jù)被全部寫(xiě)入操作系統(tǒng)緩存區(qū)時(shí)觸發(fā) |
| pipe | 當(dāng)用于讀取數(shù)據(jù)的pipe方法被調(diào)用時(shí)觸發(fā) |
| unpipe | 當(dāng)用于讀取數(shù)據(jù)的pipe方法被調(diào)用時(shí)觸發(fā) |
| error | 當(dāng)寫(xiě)入數(shù)據(jù)的過(guò)程中產(chǎn)生錯(cuò)誤時(shí)觸發(fā) |
這些對(duì)象在寫(xiě)入數(shù)據(jù)的過(guò)程中,所擁有的方法如下表所示:
| 方法名 | 描述 |
|---|---|
| write | 用于寫(xiě)入有數(shù)據(jù) |
| end | 當(dāng)沒(méi)有數(shù)據(jù)再被寫(xiě)入流中時(shí)調(diào)用該方法,這將迫使操作系統(tǒng)緩存區(qū)中的剩余數(shù)據(jù)被立即寫(xiě)入目標(biāo)對(duì)象。當(dāng)該方法被調(diào)用后,將不能繼續(xù)在目標(biāo)對(duì)象中xie |
使用fs模塊的createWriteStream方法創(chuàng)建一個(gè)將流數(shù)據(jù)寫(xiě)入文件的WriteStream對(duì)象。
const fs = require('fs');
let file = fs.createWriteStream('./result.txt');
file.write('hello Node.js',function(){
console.log('寫(xiě)入文件')
})