ReadableStream 簡單實現

2021-09-11 13:59:47 字數 4434 閱讀 9872

今天的文章需要提前了解一下nodefs模組的相關api,不太熟悉的同學可以點這裡。

眾所周知,node中的fs模組功能大都與檔案相關,比如可以通過fs.createreadstream建立檔案可讀流,通過fs.createwritestream建立檔案可寫流,還可以通過監聽opendataenderrorreadable事件對資料進行操作。由於時間有限,今天我們先來實現一下readable事件功能。

開始之前,先簡單介紹一下可讀流函式fs.createreadstream(path[, options])中各引數所代表的含義,如下所示:

首先我們需要實現乙個可讀流的類,不防定義為readablestream,該類可以通過on函式進行事件監聽,所以需要繼承nodeeventemitter類; 當監聽readable函式時可讀取到檔案內容,由此得知在建構函式中除了需要定義上面的變數,還需要呼叫開啟檔案和第一次讀取檔案的功能。**如下:

let fs = require('fs')

let eventemitter = require('events')

class

readablestream

extends

eventemitter

})}}

module.exports = readablestream

複製**

建構函式中其它變數可以先忽略,到實現階段時我相信大家自然清晰其用處。 下面利用fs.openfs.destory實現opendestory功能。實現**如下:

// 開啟可讀流

open()

return

}this.fd = fd

this.emit('open')

})}// 關閉可讀流,引數為檔案描述符

destory() )

} this.emit('close')

}複製**

接下來看下初次讀取時的read函式。

實現思路:在建構函式中,當觸發第一次讀取檔案時,讀取大小為highwatermark個,不防我們將比較讀取長度和快取長度的方法設定為read。然後再read函式中判斷,如果快取區長度為0時,表明可以觸發readable事件;如果快取區長度小於水位線時,則進行檔案讀取,此時我們將真正讀取檔案的函式命名為_read;最後,根據編碼格式進行返回資料。

實現**如下:

class

readablestream

extends

eventemitter

// 如果快取區長度小於水位線時,則進行檔案讀取

if (this.len < this.highwatermark)

}// 根據編碼方式處理資料

if (buffer)

return buffer

} // 真實讀取檔案的方法

_read ()

let howmuchtoread = this.end ? math.min(this.highwatermark, this.end - this.pos + 1) : this.highwatermark

let buffer = buffer.alloc(howmuchtoread)

fs.read(this.fd, buffer, 0, this.howmuchtoread, this.pos, (err, bytesread) => }})

} // 此處如上,省略...

}複製**

當前1.txt檔案中的內容為1234567890。呼叫方式如下:

let fs = require('fs')

let readablestream = require('./readablestream')

let rs = new readablestream('./1.txt', )

rs.on('readable', () => )

複製**

接下來從快取區中讀取資料。

當讀取長度小於水位線時,使用原生方式呼叫,可以得到如下結果:

let fs = require('fs')

let rs = fs.createreadstream('./1.txt', )

rs.on('readable', () => )

複製**

由此可知,如果緩衝區內容夠讀,則返回結果結束讀取。實現**如下:

class

readablestream

extends

eventemitter

// 如果讀取長度小於快取區長度,this.read(2) highwatermark=3

if (n > 0 && n <= this.len)

this.len -= n

break}}

}}

// 如果快取區長度為0時,表明可以觸發readable事件

if (this.len === 0)

// 如果快取區長度小於水位線時,則進行檔案讀取

if (this.len < this.highwatermark)

}// 根據編碼方式處理資料

if (buffer)

return buffer

} // 此處如上,省略...

}複製**

當讀取長度等於水位線時,使用原生方式呼叫,可以得到如下結果:

let fs = require('fs')

let rs = fs.createreadstream('./1.txt', )

rs.on('readable', () => )

複製**

由此可知,如果緩衝區內容讀完為空,則返回結果繼續讀取。實現**如下:

class

readablestream

extends

eventemitter

// 如果快取區長度小於水位線時,則進行檔案讀取

if (this.len < this.highwatermark)

}// 此處如上,省略...

return buffer

} // 此處如上,省略...

}複製**

當讀取長度大於水位線時,使用原生方式呼叫,可以得到如下結果:

let fs = require('fs')

let rs = fs.createreadstream('./1.txt', )

rs.on('readable', () => )

複製**

由此可知,如果緩衝區內容不夠讀,初次會返回null,然後修改highwatermark值繼續讀取返回,即為12345678。此時,this.len不等於0且小於this.highwatermark,會再次呼叫_read方法,如果讀取檔案為空,則需要手動觸發一下readable事件。實現**如下:

class

readablestream

extends

eventemitter

else

}// 此處如上,省略...

return buffer

} // 真實讀取檔案的方法

_read () else else }})

} // 此處如上,省略...

}複製**

計算highwatermark的函式如下:

function

computenewhighwatermark (n)

複製**

原始碼

???,好了,全部功能已經實現,就到此結束吧!

JS簡簡簡易時鐘

簡易時鐘 1 搭建html css部分 插入時鐘背景,使用子絕父相。把時針和分針 秒針的樣式放在時鐘的中心位置 2 js邏輯部分 1 獲取時針 分針 秒針 var hour document.getelementbyid hour var min document.getelementbyid mi...

Metasploit Framework 簡單介紹

1.簡介 metasploit framework 是乙個緩衝區溢位測試使用的輔助工具,也可以說是乙個漏洞利用和測試平台。它整合了各平台上常見的溢位漏洞和流行的shellcode,並且不斷更新,使得緩衝區溢位測試變得方便和簡單。2.主頁 1 選定使用的漏洞 use 2 設定漏洞利用的環境 targe...

android PagerAdapter簡單應用

pageradapter是android.support.v4包中的類,它的子類有fragmentpageradapter fragmentstatepageradapter,這兩個adapter都是fragment的介面卡,用於實現fragment的滑動效果 pageradapter主要是view...