Node之IO

Buffer

Buffer的構(gòu)成

Buffer對象類似數(shù)組,它的元素位16進制的兩位數(shù),即0到255的數(shù)值。主要是用來存儲二進制的數(shù)據(jù)

const buf = Buffer.from('Hello world')

初始化Buffer會隨機的填充了0到255的隨機值

var buffer = new Buffer(100);
buffer[20] = -100;

console.log(buffer[20]) // 如果存儲的數(shù)字小于0或者大于255則直接加值256知道值位于0到255之間

Buffer的底層分配

Node從c++層面申請內(nèi)存,在JS層面用來分配內(nèi)存的策略,Buffer在C++申請內(nèi)存主要是8K。

Buffer的轉(zhuǎn)換

目前Buffer的對象是可以直接與字符串進行互相轉(zhuǎn)換,目前支持的字符串編碼類型有

  • ASCII

  • UTF-8

  • UTF-16

  • Base64

  • Binary

  • Hex

    目前官方暫時不支持漢字編碼GBK之類,如果有類似的漢字編碼需求需要調(diào)用第三方庫的支持。

Buffer的亂碼現(xiàn)象

因為Buffer對象只要是用于二進制與字符串的轉(zhuǎn)換,一旦設(shè)計編碼 解碼就會出現(xiàn)所謂的亂碼現(xiàn)象,特別是出現(xiàn)在漢字編碼問題。

var rs = fs.createReadStream('buffer.txt',{
  highWaterMark:11
});

var data = '';
rs.on('data',(thunk)=>{
  data +=thunk; // data.toString() += thunk.toString()
})

rs.on('end',()=>{
  console.log(data);
})

在Options上選擇了highWaterMark,主要是影響操作系統(tǒng)讀取文件的字節(jié)塊,目前是按照11字節(jié)讀取,因為漢字在UTF-8中編碼只要是三個字節(jié),所以在讀取漢字的時候可能會出現(xiàn)兩個字節(jié)導(dǎo)致無法編碼,出現(xiàn)所謂的亂碼現(xiàn)象。

亂碼解決方案

  • stream.setEncoding('utf-8') 這樣當(dāng)stream讀取到中文漢字需要解碼的時候 底層的string_decoder 則會收集完整的字節(jié)然后解碼顯示漢字
  • 通過將stream中的數(shù)據(jù)接受完整數(shù)據(jù)后,然后指定編碼符來統(tǒng)一解碼。

Stream

Node.js中有四種基本的流類型:

  • Readable 可讀的流(例如 fs.createReadStream())
  • Writable 可寫的流 (例如 fs.createWriteStream())
  • Duplex 可讀寫的流 ( 例如 net.Socket)
  • Transform 在讀寫過程中科院修改和變換數(shù)據(jù)的Duplex流

緩沖

Writable和Readable流都會將數(shù)據(jù)存儲到內(nèi)部的緩存中。這些緩存可以通過相應(yīng)的writable._writableState.getBuffer()或者readable._readableState.buffer來獲取。 緩存的大小取決流構(gòu)造函數(shù)的highWaterMark選項。對于普通的流, highWaterMark選項指定了總共的字節(jié)數(shù)。對于工作在對象模式的流,highWaterMark指定了對象的總數(shù)。

  • 當(dāng)可讀流實現(xiàn)調(diào)用了stream.push(chunk)方法,數(shù)據(jù)被放到了緩存中,如果流的消費者沒有調(diào)用stream.read()方法,這些數(shù)據(jù)會始終存在內(nèi)部隊列,直到被消費。
  • 可寫流通過反復(fù)調(diào)用writable.write(chunk)方法將數(shù)據(jù)放到緩存。當(dāng)內(nèi)部可寫入緩存的總大小小于highWaterMark指定的閥值,調(diào)用writable.write()將返回true.
  • streamAPI的關(guān)鍵方法在于stream.pipe()方法,就是限制緩存數(shù)據(jù)大小,以達到可接受的程度。這樣,對于讀寫速度不匹配的源頭和目標(biāo)。

可寫流

Write Streams 是destination的一種抽象,這種destination允許數(shù)據(jù)寫入

Writable的例子包括了

  • HTTP request, on the client
  • HTTP response, on the server
  • fs write streams
  • lib streams
  • crypto streams
  • TCP sockets
  • child process stdin

Writeable流暴露了一些方法 比如write() end() pipe()方法

Writable類的事件和方法

  • close事件 底層資源關(guān)閉后觸發(fā) close事件觸發(fā)后,該流將不會再觸發(fā)任何事件
  • drain 事件 當(dāng)stream.write(chunk)方法返回false 出發(fā) 此時才能繼續(xù)讓緩沖區(qū)寫入數(shù)據(jù)
  • error事件 stream寫入數(shù)據(jù)出錯
  • finish 事件 stream.end()方法
  • pipe 事件 輸出到目標(biāo)可寫入流的源流 stream.pipe() 方法
  • writable.cork() 強制將所有寫入數(shù)據(jù)源都放入內(nèi)存中的緩沖區(qū)
  • writable.end(chunk, encoding, callback)
  • writable.setDefaultEncoding
  • writable.write(chunk,encoding,callback)
  • writable.destroy(error)

可讀流

Readable的例子

  • HTTP response, on the client
  • HTTP request , on the server
  • fs read streams
  • zlib streams
  • crypto streams
  • TCP sockets
  • child process stdin

可讀流的時間和方法

  • close事件
  • data事件
  • end事件
  • error事件
  • readable.pause()
  • readable.pipe()
  • readable.unpipe()
  • readable.setEncoding(encoding)
  • readable.destory(error)

兩種模式

可讀流事實上工作在下面兩種模式之一: flowing 和paused

在flowing模式下,可讀流自動從系統(tǒng)底層讀取數(shù)據(jù),并通過EventEmitter接口的事件盡快將數(shù)據(jù)提供給應(yīng)用

在paused模式下,必須顯示調(diào)用stream,read()方法來從流中讀取數(shù)據(jù)片段

所有初始工作位paused的Readable流,可以通過下面三種途徑切換到flowing模式:

  • 監(jiān)聽了'data'事件
  • 調(diào)用了stream.resume()方法
  • 調(diào)用了stream.pipe()方法將數(shù)據(jù)發(fā)送Writable

從Flowing模式切換到paused模式

  • 如果存在了管道目標(biāo),可以通過取消'data'事件箭筒,并調(diào)用stream.unpipe()方法移除所有管道目標(biāo)來實現(xiàn)
  • 如果不存在管道目標(biāo),直接調(diào)用stream.pause()方法來實現(xiàn)

三種狀態(tài)

任意可讀流應(yīng)確切處于下面三種狀態(tài):

  • readable._readableState.flowing = null

    由于不存在數(shù)據(jù)消費者,可讀流將不會產(chǎn)生數(shù)據(jù)

  • readable._readableState.flowing = false

    調(diào)用 readable.pause() 方法, readable.unpipe() 方法, 或者接收 “背壓”(back pressure), 將導(dǎo)致 readable._readableState.flowing 值變?yōu)?false。 這將暫停事件流,但 不會 暫停數(shù)據(jù)生成。

  • readable._readableState.flowing = true

    當(dāng)stream監(jiān)聽了 'data'事件 調(diào)用了pipe方法,或者調(diào)用readable.resume()方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,283評論 6 530
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 97,947評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,094評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,485評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,268評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,817評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,906評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,039評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,551評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,502評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,662評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,188評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,907評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,304評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,563評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,255評論 3 389
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,637評論 2 370

推薦閱讀更多精彩內(nèi)容

  • stream 流是一個抽象接口,在 Node 里被不同的對象實現(xiàn)。例如 request to an HTTP se...
    明明三省閱讀 3,417評論 1 10
  • 流是Node中最重要的組件和模式之一。在社區(qū)里有一句格言說:讓一切事務(wù)流動起來。這已經(jīng)足夠來描述在Node中流...
    宮若石閱讀 566評論 0 0
  • https://nodejs.org/api/documentation.html 工具模塊 Assert 測試 ...
    KeKeMars閱讀 6,355評論 0 6
  • 為什么應(yīng)該使用流 你可能看過這樣的代碼。 這段代碼中,服務(wù)器每收到一次請求,就會先把data.txt讀入到內(nèi)存中,...
    饑人谷_xxxxx閱讀 10,825評論 1 12
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,775評論 18 139