使用buffer類處理二進制數據
在客戶端javascript腳本代碼中,對於二進制數據並沒有提供一個很好的支持。然后在nodejs中需要處理像TCP流或文件流時,必須要處理二進制數據。因此在node.js中,定義了一個Buffer類,該類用來創建一個專門存放二進制數據的緩存區。
一:創建Buffer對象
在node.js中,Buffer類是一個可以在任何模塊被利用的全局類,不需要為該類的使用而加載任何模塊。可以使用new關鍵字來創建該類的實例對象。Buffer類可以使用三種方式來構造函數,第一種方式如下:
new Buffer(size)
被創建的buffer對象擁有一個length屬性,屬性值為緩存區的大小。如下:
我們現在也可以使用Buffer對象的fill方法來初始化緩存區中的所有內容,如下所示:
buf.fill(value,[offset],[end]);
在Buffer對象的fill方法中,可以使用三個參數,第一個參數為必須指定的參數,參數值為需要被寫入的數值,第二個參數與第三個參數為可選參數,其中第二個參數用於指定從第幾個字節處開始寫入被指定的數值,默認值為0,即從緩存區的起始位置寫入,第三個參數用於指定將數值一直寫入到第幾個字節處,默認值為Buffer對象的大小,即書寫到緩存區的底部。
現在我們希望從buffer對象的緩存區的第10字節處開始寫入1,一直到緩存區底部,如下所示:
我們現在也可以在緩存區的第20到第30字節處(從第20字節開始,不包含第30字節)填入2,演示如下:
Buffer類的第二種形式的構造函數是直接使用一個數組來初始化緩存區,代碼如下所示:
new Buffer(array)
演示如下:
Buffer類的第三種形式的構造函數是直接使用一個字符串來初始化緩存區,代碼如下:
new Buffer(str,[encoding]);
第一個參數為必須指定的參數,參數值為用於初始化換出區的字符串,第二個參數值為一個用於指定文字編碼格式的字符串,默認值為utf-8
如下所示:
在Node.js中,將自動執行字符串的輸入輸出時的編碼與解碼處理,默認使用utf-8編碼,可以使用編碼格式如下表所示:
編碼 | 說明 |
ascii | ASCLL字符串 |
utf8 | UTF-8字符串 |
utf16le | UTF-16LE字符串 |
ucs2 | UCS2字符串 |
base64 | 經過BASE64編碼后的字符串 |
binary | 二進制數據(不推薦使用) |
hex | 使用16進制數值表示的字符串 |
當使用字符串參數來創建buffer對象並初始化緩存區時,如果使用不同的編碼格式,則緩存區中的數據也會有所不同,如下演示:
二:字符串的長度與緩存區的長度
在node.js中,一個字符串的長度與根據該字符串所創建的緩存區的長度並不相同,因為在計算字符串的長度時,是以文字作為一個單位,而在計算緩存區的長度時,是以字節作為一個單位。
比如針對 ”我喜愛編程”這個字符串,該字符串對象的length屬性值與根據該字符串創建的buffer對象的length屬性值並不相同。因為字符串對象的length屬性值獲取的是文字個數,而buffer對象的length屬性值獲取的是緩存區的長度,即緩存區中的字節。
另外,可以使用0開始的序號來取出字符串對象或緩存區中的數據。但是,在獲取數據時,字符串對象是以文字作為一個單位,而緩存區對象是以字節作為一個單位。比如,針對一個引用了字符串對象的str變量來說,str[2]獲取的是第三個文字,而針對一個引用了緩存區對象的buf對象來說,buf[2]獲取的是緩存區中的第三個字節數據轉換為整數后的數值。如下:
而buffer對象是可以被修改的。可以通過序號來修改其中某個字節處的數據。如下:
Buffer對象還有一個用於取出指定位置處數據的slice方法,該方法的使用方法與string對象的slice方法相同。
注意:由於buffer對象的slice方法並不是復制緩存區中的數據,而是與該數據共享內存區域,因此,如果修改使用slice方法取出的數據,則緩存區中保存的數據也將被修改。如下演示:
三:Buffer對象與字符串對象之間的相互轉換;
1. Buffer對象的toString方法
可以使用Buffer對象的toString方法將Buffer對象中保存的數據轉換為字符串,使用方法如下所示:
buf.toString([encoding],[start],[end]);
在Buffer對象的toString方法中,可以使用三個可選參數,第一個參數用於指定Buffer對象中保存的文字編碼格式,默認參數值為utf8,第二個及第三個用於指定被轉換數據的起始位置和終止位置,以字節為單位。toString方法返回經過轉換后的字符串。
四:Buffer對象的write方法
如果要將字符串當做二進制數據來使用,只需將該字符串作為Buffer類的構造函數的參數來創建Buffer對象即可。但是有時候我們需要向已經創建好的Buffer對象中寫入字符串,這時候我們可以使用Buffer對象的write方法,代碼如下所示:
buf.write(string,[offset],[length],[encoding]);
在buffer對象的write方法中,可以使用四個參數,第一個參數為必須指定的參數,后三個參數為可選參數,第一個參數用於指定需要寫入的字符串,第二個參數offset與第三個參數length用於指定字符串轉換為字節數據的寫入位置。字節數據的書寫位置為從第1+offset個字節開始到offset+length個字節為止(列如offset為3,length為8,寫入位置為從第4個字節開始到第11個字節為止,包括第4個字節與第11個字節)。第四個參數用於指定寫入字符串時使用的編碼格式,默認是utf8格式。
如下代碼演示:
五:Buffer對象與JSON對象之間的相互轉換
在Node.js中,可以使用JSON.stringfy方法將Buffer對象中保存的數據轉換為一個字符串,也可以使用JSON.parse方法將一個經過轉換后的字符串還原為一個數組。
六:復制緩存數據。
當需要將Buffer對象中保存的二進制數據復制到另一個Buffer對象中時,可以使用Buffer對象的copy方法,copy方法的使用方法如下所示:
buf.copy(targetBuffer,[targetStart],[sourceStart],[sourceEnd]);
在Buffer對象的copy方法中,使用四個參數,第一個參數為必須指定的參數,其余三個參數均為可選參數。第一個參數用於指定復制的目標Buffer對象。第二個參數用於指定目標Buffer對象中從第幾個字節開始寫入數據,參數值為一個小於目標的Buffer對象長度的整數值,默認值為0(從開始處寫入數據)。第三個參數用於指定從復制源Buffer對象中獲取數據時的開始位置,默認值為0,即從復制源Buffer對象中的第一個字節開始獲取數據,第四個參數用於指定從復制源Buffer對象中獲取數據時的結束位置,默認值為復制源Buffer對象的長度,即一直獲取完畢復制源Buffer對象中的所有剩余數據。
比如如下:將a中buffer對象中的內容復制到b中的buffer對象中,復制的目標起始位置為b的buffer對象中的第11字節處(第11字節處開始寫入)。如下所示:
七:Buffer類的類方法
- isBuffer方法
isBuffer方法用於判斷一個對象是否為一個Buffer對象,使用方法如下:
Buffer.isBuffer(obj)
在isBuffer方法中,使用一個參數,用於指定需要被判斷的對象,如果對象為Buffer對象,方法返回true,否則返回false。演示如下:
2. byteLength方法;
可以使用byteLength方法計算一個指定字符串的字節數,使用方法如下所示:
Buffer.byteLength(string,[encoding]);
在byteLength方法中,使用兩個參數,第一個參數為必須輸入的參數,用於指定需要計算字節數的字符串,第二個參數為可選參數,用於指定按什么編碼方式來計算字節數。默認值為utf8.
如下演示:
3. concat方法。
concat方法用於將幾個Buffer對象結合創建為一個新的Buffer對象,使用方法如下所示:
Buffer.concat(list,[totalLength])
在concat方法中,使用兩個參數,第一個參數為必須指定的參數,參數值為一個存放了多個buffer對象的數組,concat方法將把其中的所有Buffer對象鏈接創建為一個Buffer對象;第二個參數為可選參數,用於指定被創建的Buffer對象的長度,當省略該參數時,被創建的Buffer對象為第一個參數數組中所有Buffer對象的長度的合計值。
如果一個參數值為一個空數組或第二個參數值等於0,那么concat方法返回一個長度為0的Buffer對象。
如果第一個參數值數組中只有一個Buffer對象,那么concat方法直接返回該Buffer對象。
如果第一個參數值數組中擁有一個以上的Buffer對象,那么concat方法返回被創建的Buffer對象。
如下演示:
4. isEncoding方法。
isEncoding方法用於檢測一個字符串是否為一個有效的編碼格式字符串,使用方法如下所示:
Buffer.isEncoding(encoding);
在isEncoding方法中,使用一個參數,用於指定需要被檢測的字符串。如果該字符串為有效的編碼格式字符串,則方法返回true,如果該字符串不是一個有效的編碼格式字符串,則方法返回false。如下演示: