官术网_书友最值得收藏!

2.2 Buffer

Buffer是Node特有(區別于瀏覽器JavaScript)的數據類型,主要用來處理二進制數據,在前端JavaScript中,和二進制數據打交道的機會比較少(ES2015增加了ArrayBuffer類型,用來操作二進制數據流,Node也可以使用該類型,我們會在下一章介紹)。而Node在進行Web開發時經常需要和前端進行數據通信,二進制數據流十分常見(例如傳輸一張gif圖片),因此Node除了String外,還內置了Buffer這一數據類型,它是Node作為運行時對JavaScript做的擴展。

Buffer屬于固有(built-in)類型,因此無須使用require進行引入。

在文件操作和網絡操作中,如果不顯式聲明編碼格式,其返回數據的默認類型就是Buffer。例如下面讀取文件的例子,如果不指定編碼格式,得到的結果就是Buffer字符串。

代碼2.2 讀取一個文件并打印內容

上面的代碼中,最后打印出的是十六進制的數據,由于純二進制格式太長而且難以閱讀,Buffer通常表現為十六進制的字符串。

2.2.1 Buffer的構建與轉換

可以使用Buffer類直接初始化一個Buffer對象,參數可以是由二進制數據組成的數組。

如果想由字符串來得到一個Buffer,同樣可以調用構造函數來實現,例如:

注意:在最新的Node API中,Buffer()方法被標記為Deprecated,表示已經不推薦使用,因為這個方法在某些情況下可能不安全(參考https://github.com/nodejs/node/issues/4660),并且會在將來的版本中將其移除。

目前推薦的是使用Buffer.from方法來初始化一個Buffer對象,上面的代碼可以改寫為如下形式。

代碼2.3 使用Buffer.from來初始化一個Buffer

如果想把一個Buffer對象轉成字符串形式,需要使用toString方法,調用格式為:

Buffer支持的編碼類型種類有限,只有以下6種:

  • ASCII
  • Base64
  • Binary
  • Hex
  • UTF-8
  • UTF-16LE/UCS-2

不過也已經覆蓋了最常用的編碼類型。Buffer還提供了isEncoding方法來判斷是否支持轉換為目標編碼格式。

例如,如果我們想把上一節表示“Hello Node”的Buffer對象轉換為字符串,那么可以調用:

如果toString在調用時不包含任何參數,那么就會默認采用UTF-8編碼,并轉換整個Buffer對象。

2.2.2 Buffer的拼接

在中國古代,有一種詩被稱作回文詩,我們先來看一個例子,如圖2-1所示。

圖2-1

這首詩是北宋秦觀所作,如果不清楚如何斷句,就無法得到正確的詩,正確的斷句:

賞花歸去馬如飛

去馬如飛酒力微

酒力微醒時已暮

醒時已暮賞花歸

Buffer一個常見的使用場景是用來處理HTTP的post請求,隨便在網絡上搜索,都能看到類似如下的代碼。

代碼2.4 使用+=來拼接Buffer

上面的代碼使用+=來拼接上傳的數據流,這個過程包含了一個隱式的編碼轉換。

body+=chunk相當于body+= chunk.toString(),當上傳字符全都是英文的時候固然沒關系,但如果字符串中包含中文或者其他語言,由于toString方法默認使用utf-8編碼,這時就有可能出現亂碼,就像回文詩不按照格式斷句,只會得到幾個不通順的句子一樣。

舉個例子,我們先構造一個中文的字符串,并將其另存為test.txt。

然后我們寫一段代碼來嘗試一下:

highWaterMark

正如其字面意思最高水位線,它表示內部緩沖區最多能容納的字節數,如果超過這個大小,就停止讀取資源文件,默認值是64KB。

假設文件大小為100KB,那么在默認情況下,系統就會每次從文件里讀取64KB大小的數據,隨后觸發data事件;chunk的大小即為highWaterMark的大小;然后接著讀取36KB大小的文件,再次觸發data事件;隨后文件讀取結束,觸發end事件。

如果highWaterMark設置得很小,那么就會發生多次系統調用,這會對性能造成影響。

由于我們要讀取的目標文件很短,因此只設置了10個字節位highWaterMark。

試著運行上面的代碼,得到下面的輸出:

可以看到輸出中產生了亂碼,我們知道utf-8中一個漢字占三個字節,那么我們將highwatermark設置為10后,每三個字之后都會有一個字被截斷,因此在調用toString方法的時候出現了亂碼。讀者也可以將每個chunk的內容打印出來看看,這里不再介紹(樸靈寫的《深入淺出Node.js》一書中用一個章節討論這個問題,建議讀者閱讀一下)。

目前上面的代碼已經被舍棄,官方的推薦做法是使用push方法來拼接Buffer,上面的代碼可改寫成下面形式:

代碼2.5 使用數組來拼接Buffer

上面的代碼在拼接過程中不會有隱式的編碼轉換,首先將Buffer放到數組里面,等待傳輸完成后再進行轉換,這樣就不會出現亂碼了。

主站蜘蛛池模板: 大冶市| 武功县| 南平市| 宿州市| 罗甸县| 黔西| 晋州市| 靖宇县| 海门市| 集贤县| 延庆县| 桓台县| 左云县| 黔东| 叙永县| 若尔盖县| 和静县| 舒兰市| 霸州市| 哈密市| 梁平县| 池州市| 施秉县| 桃源县| 稷山县| 鲁甸县| 确山县| 右玉县| 攀枝花市| 扶绥县| 司法| 沅陵县| 甘肃省| 永川市| 萝北县| 镇宁| 吉林省| 平谷区| 蓬莱市| 荥阳市| 安乡县|