欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

NodeJS中Buffer模塊詳解

 更新時(shí)間:2015年01月07日 17:13:22   投稿:hebedich  
這篇文章主要介紹了NodeJS中Buffer模塊詳解,十分的詳細(xì),需要的朋友可以參考下

一,開篇分析

所謂緩沖區(qū)Buffer,就是 "臨時(shí)存貯區(qū)" 的意思,是暫時(shí)存放輸入輸出數(shù)據(jù)的一段內(nèi)存。

JS語(yǔ)言自身只有字符串?dāng)?shù)據(jù)類型,沒有二進(jìn)制數(shù)據(jù)類型,因此NodeJS提供了一個(gè)與String對(duì)等的全局構(gòu)造函數(shù)Buffer來(lái)提供對(duì)二進(jìn)制數(shù)據(jù)的操作。除了可以讀取文件得到Buffer的實(shí)例外,還能夠直接構(gòu)造,例如:

復(fù)制代碼 代碼如下:

 var buffer = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]) ;

Buffer與字符串類似,除了可以用.length屬性得到字節(jié)長(zhǎng)度外,還可以用[index]方式讀取指定位置的字節(jié),例如:

復(fù)制代碼 代碼如下:

buffer[0] ; // 0x68;

Buffer與字符串能夠互相轉(zhuǎn)化,例如可以使用指定編碼將二進(jìn)制數(shù)據(jù)轉(zhuǎn)化為字符串:

復(fù)制代碼 代碼如下:

var str = buffer.toString("utf-8");  // hello

將字符串轉(zhuǎn)換為指定編碼下的二進(jìn)制數(shù)據(jù):

復(fù)制代碼 代碼如下:

var buffer= new Buffer("hello", "utf-8") ; // <Buffer 68 65 6c 6c 6f>

一點(diǎn)兒區(qū)別:

Buffer與字符串有一個(gè)重要區(qū)別。字符串是只讀的,并且對(duì)字符串的任何修改得到的都是一個(gè)新字符串,原字符串保持不變。

至于Buffer,更像是可以做指針操作的C語(yǔ)言數(shù)組。例如,可以用[index]方式直接修改某個(gè)位置的字節(jié)。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

slice方法也不是返回一個(gè)新的Buffer,而更像是返回了指向原Buffer中間的某個(gè)位置的指針,如下所示。

[ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]
    ^           ^
    |           |
   bin     bin.slice(2)
因此對(duì)slice方法返回的Buffer的修改會(huì)作用于原Buffer,例如:

復(fù)制代碼 代碼如下:

 var buffer= new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]) ;
 var sub = bin.slice(2) ;
 sub[0] = 0x65 ;
 console.log(buffer) ; //  <Buffer 68 65 65 6c 6f>

如果想要拷貝一份Buffer,得首先創(chuàng)建一個(gè)新的Buffer,并通過(guò).copy方法把原Buffer中的數(shù)據(jù)復(fù)制過(guò)去。

這個(gè)類似于申請(qǐng)一塊新的內(nèi)存,并把已有內(nèi)存中的數(shù)據(jù)復(fù)制過(guò)去。以下是一個(gè)例子。

復(fù)制代碼 代碼如下:

 var buffer= new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]) ;
 var dup = new Buffer(bin.length) ;
 buffer.copy(dup) ;
 dup[0] = 0x48 ;
 console.log(buffer) ;  // <Buffer 68 65 6c 6c 6f>
 console.log(dup) ;  // <Buffer 48 65 65 6c 6f>

總之,Buffer將JS的數(shù)據(jù)處理能力從字符串?dāng)U展到了任意二進(jìn)制數(shù)據(jù)。

以上簡(jiǎn)單讓大家了解一下什么是Buffer,下面具體說(shuō)說(shuō)如何使用和具體使用場(chǎng)景。

二,聊聊Buffer

JavaScript對(duì)字符串處理十分友好,無(wú)論是寬字節(jié)還是單字節(jié)字符串,都被認(rèn)為是一個(gè)字符串。Node中需要處理網(wǎng)絡(luò)協(xié)議、操作數(shù)據(jù)庫(kù)、處理圖片、文件上傳等,還需要處理大量二進(jìn)制數(shù)據(jù),自帶的字符串遠(yuǎn)不能滿足這些要求,因此Buffer應(yīng)運(yùn)而生。

Buffer結(jié)構(gòu)

Buffer是一個(gè)典型的Javascript和C++結(jié)合的模塊,性能相關(guān)部分用C++實(shí)現(xiàn),非性能相關(guān)部分用javascript實(shí)現(xiàn)。

Node在進(jìn)程啟動(dòng)時(shí)Buffer就已經(jīng)加裝進(jìn)入內(nèi)存,并將其放入全局對(duì)象,因此無(wú)需require

Buffer對(duì)象:類似于數(shù)組,其元素是16進(jìn)制的兩位數(shù)。

Buffer內(nèi)存分配

Buffer對(duì)象的內(nèi)存分配不是在V8的堆內(nèi)存中,在Node的C++層面實(shí)現(xiàn)內(nèi)存的申請(qǐng)。

為了高效的使用申請(qǐng)來(lái)得內(nèi)存,Node中采用slab分配機(jī)制,slab是一種動(dòng)態(tài)內(nèi)存管理機(jī)制,應(yīng)用各種*nix操作系統(tǒng)。slab有三種狀態(tài):

(1) full:完全分配狀態(tài)

(2) partial:部分分配狀態(tài)

(3) empty:沒有被分配狀態(tài)

Buffer的轉(zhuǎn)換
 
Buffer對(duì)象可以和字符串相互轉(zhuǎn)換,支持的編碼類型如下:

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

字符串轉(zhuǎn)Buffer

new Buffer(str, [encoding]),默認(rèn)UTF-8
buf.write(string, [offset], [length], [encoding])

Buffer轉(zhuǎn)字符串

buf.toString([encoding], [start], [end])

Buffer不支持的編碼類型

通過(guò)Buffer.isEncoding(encoding)判斷是否支持

iconv-lite:純JavaScript實(shí)現(xiàn),更輕量,性能更好無(wú)需C++到j(luò)avascript的轉(zhuǎn)換

iconv:調(diào)用C++的libiconv庫(kù)完成

Buffer的拼接

注意 "res.on('data', function(chunk) {})",其中的參數(shù)chunk是Buffer對(duì)象,直接用+拼接會(huì)自動(dòng)轉(zhuǎn)換為字符串,對(duì)于寬字節(jié)字符可能會(huì)導(dǎo)致亂碼產(chǎn)生,

解決方法:

(1) 通過(guò)可讀流中的setEncoding()方法,該方法可以讓data事件傳遞不再是Buffer對(duì)象,而是編碼后的字符串,其內(nèi)部使用了StringEncoder模塊。

(2) 將Buffer對(duì)象暫存到數(shù)組中,最后在組裝成一個(gè)大Buffer讓后編碼轉(zhuǎn)換為字符串輸出。

Buffer在文件I/O和網(wǎng)絡(luò)I/O中廣泛應(yīng)用,其性能舉足輕重,比普通字符串性能要高出很多。

Buffer的使用除了與字符串的轉(zhuǎn)換有性能損耗外,在文件讀取時(shí)候,有一個(gè)highWaterMark設(shè)置對(duì)性能影響至關(guān)重要。

a,highWaterMark設(shè)置對(duì)Buffer內(nèi)存的分配和使用有一定影響。

b, highWaterMark設(shè)置過(guò)小,可能導(dǎo)致系統(tǒng)調(diào)用次數(shù)過(guò)多。

什么時(shí)候該用buffer,什么時(shí)候不該用  ------ 純粹的javascript支持unicode碼而對(duì)二進(jìn)制不是很支持,當(dāng)解決TCP流或者文件流的時(shí)候,處理流是有必要的,我們保存非utf-8字符串,2進(jìn)制等等其他格式的時(shí)候,我們就必須得使用 ”Buffer“ 。

三,實(shí)例引入

復(fù)制代碼 代碼如下:

 var buf = new Buffer("this is text concat test !") ,str = "this is text concat test !" ;
 console.time("buffer concat test !");
 var list = [] ;
 var len = 100000 * buf.length ;
 for(var i=0;i<100000;i++){
     list.push(buf) ;
     len += buf.length ;
 }
 var s1 = Buffer.concat(list, len).toString() ;
 console.timeEnd("buffer concat test !") ;
 console.time("string concat test !") ;
 var list = [] ;
 for (var i = 100000; i >= 0; i--) {
   list.push(str) ;
 }
 var s2 = list.join("") ;
 console.timeEnd("string concat test !") ;

以下是運(yùn)行結(jié)果:

讀取速度肯定string更快,buffer還需要toString()的操作。 所以我們?cè)诒4孀址臅r(shí)候,該用string還是要用string,就算大字符串拼接string的速度也不會(huì)比buffer慢。

那什么時(shí)候我們又需要用buffer呢?沒辦法的時(shí)候,當(dāng)我們保存非utf-8字符串,2進(jìn)制等等其他格式的時(shí)候,我們就必須得使用了。

四,總結(jié)一下

(1),JavaScript適合處理Unicode編碼數(shù)據(jù),但對(duì)二進(jìn)制數(shù)據(jù)的處理并不友好。
(2),所以處理TCP流或文件系統(tǒng)時(shí),對(duì)八位字節(jié)流的處理很有必要。
(3),Node有幾個(gè)用于處理,創(chuàng)建和消耗八位字節(jié)流的方法。
(4),原始數(shù)據(jù)存放在一個(gè)Buffer實(shí)例中,一個(gè)Buffer類似一個(gè)整數(shù)數(shù)組,但是它的內(nèi)存,分配在V8堆棧外。一個(gè)Buffer的大小是不能更改的。
(5),處理的編碼類型有:ascii,utf8,utf16le,ucs2(utf16le的別名),base64,binary,hex。
(6),Buffer為全局元素,直接new Buffer()就得到一個(gè)Buffer實(shí)例。

相關(guān)文章

  • 用npm-run實(shí)現(xiàn)自動(dòng)化任務(wù)的方法示例

    用npm-run實(shí)現(xiàn)自動(dòng)化任務(wù)的方法示例

    這篇文章主要介紹了用npm-run實(shí)現(xiàn)自動(dòng)化任務(wù)的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • Node.js事件循環(huán)(Event Loop)和線程池詳解

    Node.js事件循環(huán)(Event Loop)和線程池詳解

    這篇文章主要介紹了Node.js事件循環(huán)(Event Loop)和線程池詳解,這篇文章比較淺顯地探討了有關(guān)事件循環(huán)的內(nèi)部運(yùn)作機(jī)制和技術(shù)細(xì)節(jié),都是經(jīng)過(guò)深思熟慮的,需要的朋友可以參考下
    2015-01-01
  • npm 常用命令詳解(小結(jié))

    npm 常用命令詳解(小結(jié))

    這篇文章主要介紹了npm 常用命令詳解(小結(jié)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • nodejs+koa2 實(shí)現(xiàn)模仿springMVC框架

    nodejs+koa2 實(shí)現(xiàn)模仿springMVC框架

    這篇文章主要介紹了nodejs+koa2 實(shí)現(xiàn)模仿springMVC框架,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • NodeJs入門教程之定時(shí)器和隊(duì)列

    NodeJs入門教程之定時(shí)器和隊(duì)列

    這篇文章主要給大家介紹了關(guān)于NodeJs入門教程之定時(shí)器和隊(duì)列的相關(guān)資料,文中通過(guò)示例代碼以及圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Node.js?操作本地文件及深入了解fs內(nèi)置模塊

    Node.js?操作本地文件及深入了解fs內(nèi)置模塊

    這篇文章主要介紹了Node.js?操作本地文件及深入了解fs內(nèi)置模塊,node.js作為服務(wù)端應(yīng)用,肯定少不了對(duì)本地文件的操作,像創(chuàng)建一個(gè)目錄、創(chuàng)建一個(gè)文件、讀取文件內(nèi)容等都是我們開發(fā)中經(jīng)常需要用到的功能
    2022-09-09
  • nodejs操作mongodb的增刪改查功能實(shí)例

    nodejs操作mongodb的增刪改查功能實(shí)例

    這篇文章主要介紹了nodejs操作mongodb的增刪改查功能,簡(jiǎn)單分析了mongodb模塊的安裝并結(jié)合實(shí)例形式分析了nodejs操作mongodb數(shù)據(jù)庫(kù)進(jìn)行增刪改查的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-11-11
  • 利用yarn代替npm管理前端項(xiàng)目模塊依賴的方法詳解

    利用yarn代替npm管理前端項(xiàng)目模塊依賴的方法詳解

    這篇文章主要給大家介紹了關(guān)于利用yarn代替npm管理前端項(xiàng)目模塊依賴的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • nodejs后臺(tái)集成ueditor富文本編輯器的實(shí)例

    nodejs后臺(tái)集成ueditor富文本編輯器的實(shí)例

    本篇文章主要介紹了nodejs后臺(tái)集成ueditor富文本編輯器的實(shí)例,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-07-07
  • Nodejs探秘之深入理解單線程實(shí)現(xiàn)高并發(fā)原理

    Nodejs探秘之深入理解單線程實(shí)現(xiàn)高并發(fā)原理

    這篇文章主要介紹了Nodejs單線程實(shí)現(xiàn)高并發(fā)原理,對(duì)Node.js感興趣的同學(xué),可以參考下
    2021-04-04

最新評(píng)論