欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

Node中的Buffer類怎么使用

這篇文章主要介紹了Node中的Buffer類怎么使用的相關知識,內(nèi)容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Node中的Buffer類怎么使用文章都會有所收獲,下面我們一起來看看吧。

成都創(chuàng)新互聯(lián)專注于永州企業(yè)網(wǎng)站建設,自適應網(wǎng)站建設,商城網(wǎng)站建設。永州網(wǎng)站建設公司,為永州等地區(qū)提供建站服務。全流程按需定制制作,專業(yè)設計,全程項目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務

TypedArray出來之前,JavaScript這門語言是不能很好地處理原始二進制數(shù)據(jù)(raw binary data)的,這是因為一開始的時候JavaScript主要還是應用在瀏覽器中作為腳本語言使用,所以需要處理原生二進制數(shù)據(jù)的場景是少之又少。而Node出來后,由于服務端的應用需要處理大量的二進制流例如文件讀寫TCP連接等,所以Node在JavaScript(V8)之外,定義了一種新的數(shù)據(jù)類型Buffer。由于Buffer在Node應用中使用十分廣泛,所以只有真正掌握了它的用法,你才能寫出更好的Node應用。

二進制基礎

在正式介紹Buffer的具體用法之前,我們先來簡單回顧一下有關二進制的知識。

身為程序員,我們應該都不會對二進制感到陌生,因為計算機所有的數(shù)據(jù)底層都是以二進制(binary)的格式儲存的。換句話來說你電腦里面的文件,不管是純文本還是圖片還是視頻,在計算機的硬盤里面都是由01這兩個數(shù)字組成的。在計算機科學中我們把0或者1單個數(shù)字叫做一個比特(bit),8個比特可以組成一個字節(jié)(byte)。十進制(decimal)數(shù)字16如果用1個字節(jié)來表示的話,底層存儲結(jié)構是:Node中的Buffer類怎么使用我們可以看到16用二進制表示的話相比于十進制的表示一下子多了6位數(shù)字,如果數(shù)字再大點的話二進制的位數(shù)會更多,這樣我們無論是閱讀還是編寫起來都很不方便。因為這個原因,程序員一般喜歡用十六進制(hexadecimal)來表示數(shù)據(jù)而不是直接使用二進制,例如我們在寫CSS的時候color的值用的就是16進制(例如#FFFFFF)而不是一堆0和1。

字符編碼

既然所有數(shù)據(jù)底層都是二進制,網(wǎng)絡傳輸?shù)臄?shù)據(jù)也是二進制的話,為什么我們現(xiàn)在閱讀的文章是中文而不是一堆01呢?這里就要介紹一下字符編碼的概念了。所謂的字符編碼簡單來說就是一個映射關系表,它表示的是字符(中文字符、英文字符或者其它字符)是如何和二進制數(shù)字(包含若干個字節(jié))對應起來的。舉個例子,如果使用我們熟悉的ascii來編碼,a這個英文字符的二進制表示是0b01100001(0b是二進制數(shù)字的前綴)。因此當我們的電腦從某個以ascii編碼的文件中讀取到0b01100001這串二進制數(shù)據(jù)時,就會在屏幕中顯示a這個字符,同樣a這個字符保存到計算機中或者在網(wǎng)絡上傳輸都是0b01100001這個二進制數(shù)據(jù)。除了ascii碼,常見的字符編碼還有utf-8utf-16等。

Buffer

掌握了基本的二進制知識字符編碼的概念后,我們終于可以正式學習Buffer了。我們先來看一下Buffer的官方定義:

The Buffer class in Node.js is designed to handle raw binary data. Each buffer corresponds to some raw memory allocated outside V8. Buffers act somewhat like arrays of integers, but aren't resizable and have a whole bunch of methods specifically for binary data. The integers in a buffer each represent a byte and so are limited to values from 0 to 255 inclusive. When using console.log() to print the Buffer instance, you'll get a chain of values in hexadecimal values.

簡單來說所謂的Buffer就是Node在V8堆內(nèi)存之外分配的一塊固定大小的內(nèi)存空間。當Buffer被用console.log打印出來時,會以字節(jié)為單位,打印出一串以十六進制表示的值。

創(chuàng)建Buffer

了解完Buffer的基本概念后,我們再來創(chuàng)建一個Buffer對象。創(chuàng)建Buffer的方式有很多種,常見的有Buffer.alloc,Buffer.allocUnsafeBuffer.from。

Buffer.alloc(size[, fill[, encoding]])

這是最常見的創(chuàng)建Buffer的方式,只需要傳入Buffer的大小即可

const buff = Buffer.alloc(5)

console.log(buff)
// Prints: <Buffer 00 00 00 00 00>

上面的代碼中我創(chuàng)建了一個大小為5個字節(jié)的Buffer區(qū)域,console.log函數(shù)會打印出五個連續(xù)的十六進制數(shù)字,表示當前Buffer儲存的內(nèi)容。我們可以看到當前的Buffer被填滿了0,這是Node默認的行為,我們可以設置后面兩個參數(shù)fillencoding來指定初始化的時候填入另外的內(nèi)容。

這里值得一提的是我在上面的代碼中使用的是Node全局的Buffer對象,而沒有從node:buffer包中顯式導入,這完全是因為編寫方便,在實際開發(fā)中應該采用后者的寫法:

import { Buffer } from 'node:buffer'

Buffer.allocUnsafe(size)

Buffer.allocUnsafeBuffer.alloc的最大區(qū)別是使用allocUnsafe函數(shù)申請到的內(nèi)存空間是沒有被初始化的,也就是說可能還殘留了上次使用的數(shù)據(jù),因此會有數(shù)據(jù)安全的問題allocUnsafe函數(shù)接收一個size參數(shù)作為buffer區(qū)域的大小:

const buff = Buffer.allocUnsafe(5)

console.log(buff)
// Prints (實際內(nèi)容可能有出入): <Buffer 8b 3f 01 00 00>

從上面的輸出結(jié)果來看我們是控制不了使用Buffer.allocUnsafe分配出來的buffer內(nèi)容的。也正是由于不對分配過來的內(nèi)存進行初始化所以這個函數(shù)分配Buffer的速度會比Buffer.alloc更快,我們在實際開發(fā)中應該根據(jù)自己實際的需要進行取舍。

Buffer.from

這個函數(shù)是我們最常用的創(chuàng)建Buffer的函數(shù),它有很多不同的重載,也就是說傳入不同的參數(shù)會有不同的表現(xiàn)行為。我們來看幾個常見的重載:

Buffer.from(string[, encoding])

當我們傳入的第一個參數(shù)是字符串類型時,Buffer.from會根據(jù)字符串的編碼(encoding參數(shù),默認是utf8)生成該字符串對應的二進制表示??磦€例子:

const buff = Buffer.from('你好世界')

console.log(buff)
// Prints: <Buffer e4 bd a0 e5 a5 bd e4 b8 96 e7 95 8c>
console.log(buff.toString())
// Prints: '你好世界'
console.log(buff.toString('ascii'))
// Prints: ''d= e%=d8\x16g\x15\f''

在上面例子中,我使用"你好世界"這個字符串完成了Buffer的初始化工作,由于我沒有傳入第二個encoding參數(shù),所以默認使用的是utf8編碼。后面我們通過查看第一個console.log的輸出可以發(fā)現(xiàn),雖然我們傳入的字符串只有四個字符,可是初始化的Buffer卻有12個字節(jié),這是因為utf8編碼中一個漢字會使用3個字節(jié)來表示。接著我們通過buff.toString()方法來查看buff的內(nèi)容,由于toString方法的默認編碼輸出格式是utf8,所以我們可以看到第二個console.log可以正確輸出buff儲存的內(nèi)容。不過在第三個console.log中我們指定了字符的編碼類型是ascii,這個時候我們會看到一堆亂碼。看到這里我想你對我之前提到的字符編碼一定有更深的認識了。

Buffer.from(buffer)

當Buffer.from接收的參數(shù)是一個buffer對象時,Node會創(chuàng)建一個新的Buffer實例,然后將傳進來的buffer內(nèi)容拷貝到新的Buffer對象里面。

const buf1 = Buffer.from('buffer')
const buf2 = Buffer.from(buf1)

console.log(buf1)
// Prints: <Buffer 62 75 66 66 65 72>
console.log(buf2)
// Prints: <Buffer 62 75 66 66 65 72>

buf1[0] = 0x61

console.log(buf1.toString())
// Prints: auffer
console.log(buf2.toString())
// Prints: buffer

在上面的例子中,我們先創(chuàng)建了一個Buffer對象buf1,里面存儲的內(nèi)容是"buffer"這個字符串,然后通過這個Buffer對象初始化了一個新的Buffer對象buf2。這個時候我們將buf1的第一個字節(jié)改為0x61(a的編碼),我們發(fā)現(xiàn)buf1的輸出變成了auffer,而buf2的內(nèi)容卻沒有發(fā)生變化,這也就印證了Buffer.from(buffer)是數(shù)據(jù)拷貝的觀點。

?注意:當Buffer的數(shù)據(jù)很大的時候,Buffer.from拷貝數(shù)據(jù)的性能是很差的,會造成CPU占用飆升,主線程卡死的情況,所以在使用這個函數(shù)的時候一定要清楚地知道Buffer.from(buffer)背后都做了什么。筆者就在實際項目開發(fā)中踩過這個坑,導致線上服務響應緩慢!

Buffer.from(arrayBuffer[, byteOffset[, length]])

說完了buffer參數(shù),我們再來說一下arrayBuffer參數(shù),它的表現(xiàn)和buffer是有很大的區(qū)別的。ArrayBuffer是ECMAScript定義的一種數(shù)據(jù)類型,它簡單來說就是一片你不可以直接(或者不方便)使用的內(nèi)存,你必須通過一些諸如Uint16ArrayTypedArray對象作為View來使用這片內(nèi)存,例如一個Uint16Array對象的.buffer屬性就是一個ArrayBuffer對象。當Buffer.from函數(shù)接收一個ArrayBuffer作為參數(shù)時,Node會創(chuàng)建一個新的Buffer對象,不過這個Buffer對象指向的內(nèi)容還是原來ArrayBuffer的內(nèi)容,沒有任何的數(shù)據(jù)拷貝行為。我們來看個例子:

const arr = new Uint16Array(2)

arr[0] = 5000
arr[1] = 4000

const buf = Buffer.from(arr.buffer)

console.log(buf)
// Prints: <Buffer 88 13 a0 0f>

// 改變原來數(shù)組的數(shù)字
arr[1] = 6000

console.log(buf)
// Prints: <Buffer 88 13 70 17>

從上面例子的輸出我們可以知道,arrbuf對象會共用同一片內(nèi)存空間,所以當我們改變原數(shù)組的數(shù)據(jù)時,buf的數(shù)據(jù)也會發(fā)生相應的變化。

其它Buffer操作

看完了創(chuàng)建Buffer的幾種做法,我們接著來看一下Buffer其它的一些常用API或者屬性

buf.length

這個函數(shù)會返回當前buffer占用了多少字節(jié)

// 創(chuàng)建一個大小為1234字節(jié)的Buffer對象
const buf1 = Buffer.alloc(1234)
console.log(buf1.length)
// Prints: 1234

const buf2 = Buffer.from('Hello')
console.log(buf2.length)
// Prints: 5

Buffer.poolSize

這個字段表示Node會為我們預創(chuàng)建的Buffer池子有多大,它的默認值是8192,也就是8KB。Node在啟動的時候,它會為我們預創(chuàng)建一個8KB大小的內(nèi)存池,當用戶用某些API(例如Buffer.alloc)創(chuàng)建Buffer實例的時候可能會用到這個預創(chuàng)建的內(nèi)存池以提高效率,下面是一個具體的例子:

const buf1 = Buffer.from('Hello')
console.log(buf1.length)
// Prints: 5

// buf1的buffer屬性會指向其底層的ArrayBuffer對象對應的內(nèi)存
console.log(buf1.buffer.byteLength)
// Prints: 8192

const buf2 = Buffer.from('World')
console.log(buf2.length)
// Prints: 5

// buf2的buffer屬性會指向其底層的ArrayBuffer對象對應的內(nèi)存
console.log(buf2.buffer.byteLength)
// Prints: 8192

在上面的例子中,buf1buf2對象由于長度都比較小所以會直接使用預創(chuàng)建的8KB內(nèi)存池。其在內(nèi)存的大概表示如圖:Node中的Buffer類怎么使用這里值得一提的是只有當需要分配的內(nèi)存區(qū)域小于4KB(8KB的一半)并且現(xiàn)有的Buffer池子還夠用的時候,新建的Buffer才會直接使用當前的池子,否則Node會新建一個新的8KB的池子或者直接在內(nèi)存里面分配一個區(qū)域(FastBuffer)。

buf.write(string[, offset,[, length]][, encoding])

這個函數(shù)可以按照一定的偏移量(offset)往一個Buffer實例里面寫入一定長度(length)的數(shù)據(jù)。我們來看一下具體的例子:

const buf = Buffer.from('Hello')

console.log(buf.toString())
// Prints: "Hello"

// 從第3個位置開始寫入'LLO'字符
buf.write('LLO', 2)
console.log("HeLLO")
// Prints: "HeLLO"

這里需要注意的是當我們需要寫入的字符串的長度超過buffer所能容納的最長字符長度(buf.length)時,超過長度的字符會被丟棄:

const buf = Buffer.from('Hello')

buf.write('LLO!', 2)
console.log(buf.toString())
// Print:s "HeLLO"

另外,當我們寫入的字符長度超過buffer的最長長度,并且最后一個可以寫入的字符不能全部填滿時,最后一個字符整個不寫入:

const buf = Buffer.from('Hello')

buf.write('LL你', 2)
console.log(buf.toString())
// Prints "HeLLo"

在上面的例子中,由于"你"是中文字符,需要占用三個字節(jié),所以不能全部塞進buf里面,因此整個字符的三個字節(jié)都被丟棄了,buf對象的最后一個字節(jié)還是保持"o"不變。

Buffer.concat(list[, totalLength])

這個函數(shù)可以用來拼接多個Buffer對象生成一個新的buffer。函數(shù)的第一個參數(shù)是待拼接的Buffer數(shù)組,第二個參數(shù)表示拼接完的buffer的長度是多少(totalLength)。下面是一個簡單的例子:

const buf1 = Buffer.from('Hello')
const buf2 = Buffer.from('World')

const buf = Buffer.concat([buf1, buf2])
console.log(buf.toString())
// Prints "HelloWorld"

上面的例子中,因為我們沒有指定最終生成Buffer對象的長度,所以Node會計算出一個默認值,那就是buf.totalLength = buf1.length + buf2.length。而如果我們指定了totalLength的值的話,當這個值比buf1.lengh + buf2.length小時,Node會截斷最后生成的buffer;如果指定的值比buf1.length + buf2.length大時,生成buf對象的長度還是totalLength,多出來的位數(shù)填充的內(nèi)容是0。

這里還有一點值得指出的是,Buffer.concat最后拼接出來的Buffer對象是通過拷貝原來Buffer對象得出來,所以改變原來的Buffer對象的內(nèi)容不會影響到生成的Buffer對象,不過這里我們還是需要考慮拷貝的性能問題就是了。

Buffer對象的垃圾回收

在文章剛開始的時候我就說過Node所有的Buffer對象分配的內(nèi)存區(qū)域都是獨立于V8堆空間的,屬于堆外內(nèi)存。那么是否這就意味著Buffer對象不受V8垃圾回收機制的影響需要我們手動管理內(nèi)存了呢?其實不是的,我們每次使用Node的API創(chuàng)建一個新的Buffer對象的時候,每個Buffer對象都在JavaScript的空間對應著一個對象(Buffer內(nèi)存的引用),這個對象是受V8垃圾回收控制的,而Node只需要在這個引用被垃圾回收的時候掛一些鉤子來釋放掉Buffer指向的堆外內(nèi)存就可以了。簡單來說Buffer分配的空間我們不需要操心,V8的垃圾回收機制會幫我們回收掉沒用的內(nèi)存。

關于“Node中的Buffer類怎么使用”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“Node中的Buffer類怎么使用”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

網(wǎng)頁標題:Node中的Buffer類怎么使用
文章源于:http://aaarwkj.com/article46/ihhgeg.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站搜索引擎優(yōu)化、網(wǎng)站策劃響應式網(wǎng)站、虛擬主機、網(wǎng)站營銷

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化
日本美女午夜福利视频| 日韩成人精品一区欧美成人| 丰满少妇诱惑在线观看| 91九色国产老熟女乱子| 在线免费观看国产不卡| 亚洲成av人天堂影院| 成人免费视频观看国产| 国产日韩一区二区三区电影| 中文字幕加勒比东京热| 国外男女性生活在线视频| 97免费观看在线观看| 蜜臀在线免费观看黄片视频| 亚洲精品色在线网站国产呦| 性感91美女白丝在线精品| 香蕉伊蕉伊中文在线视频| 亚洲女人淫片在线观看| 91国产香蕉在线观看| 久久人妻一区二区三区免费| 黄色黄色片黄色片黄色| 国产在线不卡中文字幕| 日产精品一级二级三级爱| 久久这里只有精品蜜桃| 日韩不卡在线观看免费| 一区二区三区蜜桃av| 看夫妻性生活免费视频| 好色人妻在线播放中文字幕| 周妍希浴室视频色哟哟| 人人妻人人澡人人爽久久av| 成人av男人天堂东京热| 在线观看中文字幕日韩精品| 日本高清一区二区网站| 免费黄色日韩在线观看| 国产一级黄色免费大片| 国产精品中文字幕欧美日韩| 亚洲国产传媒在线观看| 九月丁香花开综合网| 91精品国产老熟女在线| 亚洲最大成人综合福利网| 91精品婷婷国产综合| 麻豆亚洲av熟女国产| 美女被男人操国产精品|