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