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

淺談Node.js:Buffer模塊

 更新時(shí)間:2016年12月05日 16:10:46   作者:SniffRose  
本篇文章主要介紹了Node.js:Buffer模塊,詳細(xì)的介紹了創(chuàng)建Buffer實(shí)例,具有一定的參考價(jià)值,有需要的可以了解一下。

Javascript在客戶(hù)端對(duì)于unicode編碼的數(shù)據(jù)操作支持非常友好,但是對(duì)二進(jìn)制數(shù)據(jù)的處理就不盡人意。Node.js為了能夠處理二進(jìn)制數(shù)據(jù)或非unicode編碼的數(shù)據(jù),便設(shè)計(jì)了Buffer類(lèi),該類(lèi)實(shí)現(xiàn)了Uint8Array接口,并對(duì)其進(jìn)行了優(yōu)化,它的實(shí)例類(lèi)似于整型數(shù)組,但是它的大小在創(chuàng)建后便不可調(diào)整。在介紹Buffer如何使用之前,先介紹幾個(gè)知識(shí)點(diǎn)。

1、V8引擎的內(nèi)存使用限制

V8引擎最大堆內(nèi)存使用在32位系統(tǒng)上默認(rèn)為512M,在64位系統(tǒng)上是1GB,雖然可以使用--max-old-space-size參數(shù)調(diào)整該值,但還是建議要用到大內(nèi)存的時(shí)候使用Buffer或Stream,因?yàn)锽uffer的內(nèi)存分配不在V8的堆上。

2、單個(gè)Buffer實(shí)例大小限制

單個(gè)Buffer實(shí)例的大小最大數(shù)值為1GB-1(32位系統(tǒng))或2GB-1(64位系統(tǒng)),所以在創(chuàng)建Buffer實(shí)例的時(shí)候不能超過(guò)該值,或者使用readFile()方法讀取大文件,否則將拋出RangeError錯(cuò)誤。

3、8KB池

Nodejs在創(chuàng)建Buffer實(shí)例的時(shí)候,當(dāng)用戶(hù)申請(qǐng)的空間大于8KB,會(huì)直接調(diào)用內(nèi)部的createUnsafeBuffer()方法創(chuàng)建一個(gè)Buffer,如果申請(qǐng)的空間大于0且小于4KB,新的Buffer則會(huì)建立在當(dāng)前的8kb SLAB上,并更新剩余空間,如下圖所示:

下面介紹Buffer API的簡(jiǎn)單使用:

1、創(chuàng)建Buffer實(shí)例

 使用Buffer.from(), Buffer.alloc(), Buffer.allocUnsafe()等方法來(lái)創(chuàng)建一個(gè)Buffer實(shí)例,6.0版本以前直接使用構(gòu)造函數(shù)創(chuàng)建的方法new Buffer()已被丟棄,不推薦使用,因?yàn)橛锌赡軙?huì)造成內(nèi)存泄漏。
 方法Buffer.alloc(size[, fill[, encoding]]),參數(shù)含義如下:

  • size,指定buffer的長(zhǎng)度,但不能超過(guò)buffer.kMaxLength,若不是數(shù)字則報(bào)錯(cuò)
  • fill,指定初始化buffer的值,默認(rèn)為0
  • encoding,如果fill是字符串,則該參數(shù)指定fill的編碼

使用如下所示:

const buf1 = Buffer.alloc(10);
console.log(buf1);//<Buffer 00 00 00 00 00 00 00 00 00 00>
const buf2 = Buffer.alloc(10,'hello');
console.log(buf2);//<Buffer 68 65 6c 6c 6f 68 65 6c 6c 6f>
const buf3 = Buffer.alloc(10,'hello','base64');
console.log(buf3);//<Buffer 85 e9 65 85 e9 65 85 e9 65 85>

方法Buffer.allocUnsafe(size),size參數(shù)指定buffer的大小,該方法返回一個(gè)沒(méi)有初始化的buffer,因此可能還保留有敏感的數(shù)據(jù),造成信息的泄漏,建議使用buffer.fill(0)函數(shù)初始化buffer,該方法與Buffer.alloc(size, fill)是不一樣的,有可能使用8KB池。使用如下所示:

const buf4 = Buffer.allocUnsafe(10);
console.log(buf4);//<Buffer 68 fb 4d 00 00 00 00 00 08 00>,可以看出是有數(shù)據(jù)的
buf4.fill(0);
console.log(buf4);//<Buffer 00 00 00 00 00 00 00 00 00 00>

方法Buffer.allocUnsafeSlow(size),參數(shù)含義同上,該方法不會(huì)使用Buffer池,容易造成內(nèi)存的浪費(fèi),使用如下所示:

const buf5 = Buffer.allocUnsafeSlow(10);
console.log(buf5);//<Buffer 38 00 24 00 00 00 00 00 00 00>

方法Buffer.from(value,[...]),這里分為四種情況,如下所示:

第一,value為16進(jìn)制數(shù)組,將數(shù)組轉(zhuǎn)化為buffer,如果不是16進(jìn)制,則會(huì)進(jìn)行轉(zhuǎn)換,如下:

const buf6 = Buffer.from([1,2,3,5,17]);
console.log(buf6);//<Buffer 01 02 03 05 11>

第二,value為字符串,則轉(zhuǎn)換字符串為buffer,該方法會(huì)使用buffer池,如下:

const buf7 = Buffer.from('hello world!');
console.log(buf7);//<Buffer 01 02 03 05 11>

第三,value為buffer實(shí)例,則將value拷貝至新的buffer中,這里只是值的拷貝,不會(huì)共享內(nèi)存,如下:

const buf8 = Buffer.from('hello world');
const buf9 = Buffer.from(buf8);
console.log(buf8);//<Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
console.log(buf9);//<Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
buf9[0] = 0x66;
console.log(buf8);//<Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
console.log(buf9);//<Buffer 66 65 6c 6c 6f 20 77 6f 72 6c 64>

第四,value為arrayBuffer時(shí),還有兩個(gè)可選參數(shù)[, byteOffset[, length]],byteOffset指定從arrayBuffer開(kāi)始復(fù)制的位置,length復(fù)制的長(zhǎng)度。如下:

const arr = new Uint8Array(2);
arr[0] = 128;
arr[1] = 200;
const buf10 = Buffer.from(arr,0,2);
console.log(buf10);//<Buffer 80 c8>

如果引用的是arr.buffer,則新創(chuàng)建的buffer buf10與arr共享內(nèi)存,如下:

const arr = new Uint8Array(2);
arr[0] = 128;
arr[1] = 200;
const buf10 = Buffer.from(arr.buffer);
arr[0] = 254;
console.log(buf10);//<Buffer fe c8>

2、buffer解碼

使用buf.toString([encoding[, start[, end]]])方法將buffer轉(zhuǎn)換成字符串,encoding指定字符編碼,默認(rèn)為'utf8',start開(kāi)始位置,end結(jié)束位置(不包括),目前encoding只支持'ascii,utf8,utf16le,ucs2,base64,latin1,binary,hex',使用如下所示:

const buf12 = Buffer.from('我愛(ài)中國(guó)');
console.log(buf12.toString('base64'));//5oiR54ix5Lit5Zu9
console.log(buf12.toString('utf8'));//我愛(ài)中國(guó)
console.log(buf12.toString('hex'));//e68891e788b1e4b8ade59bbd

3、buffer拼接、復(fù)制、填充、分割

方法buf.fill(value[, offset[, end]][, encoding])使用指定的值填充buffer,參數(shù)offset指定填充的起始位置,end為結(jié)束位置,使用如下所示:

console.log(Buffer.allocUnsafe(5).fill('a').toString());//aaaaa
console.log(Buffer.allocUnsafe(5).fill(65).toString('utf8'));//AAAAA

方法Buffer.concat(list[, totalLength])將多個(gè)buffer合并在一起,并返回一個(gè)新的buffer實(shí)例,參數(shù)totalLength為指定的buffers的長(zhǎng)度總和,如果不提供該值,函數(shù)內(nèi)部會(huì)循環(huán)去獲取每一個(gè)buffer的長(zhǎng)度,然后進(jìn)行拼接,因此為了速度,最好指定一個(gè)總長(zhǎng)度,使用如下:

function bufferInjoin(buffArr){
  var len = 0;
  buffArr.forEach((buff,idx,arr)=>{
    len+=buff.length;
  });
  var buffer = Buffer.concat(buffArr,len);
  return buffer;
}
var buff = bufferInjoin([Buffer.from('hehe'),Buffer.allocUnsafe(5).fill('a')]);
console.log(buff);//<Buffer 68 65 68 65 61 61 61 61 61>
console.log(buff.length);//9
console.log(buff.toString());//heheaaaaa

方法buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])可以實(shí)現(xiàn)buf到target的復(fù)制,參數(shù)含義如下:

  • target,復(fù)制目標(biāo)
  • targetStart,復(fù)制目標(biāo)開(kāi)始被覆蓋的位置
  • sourceStart,復(fù)制源開(kāi)始復(fù)制的位置
  • sourceEnd,復(fù)制源復(fù)制結(jié)束的位置

使用如下所示:

const buf1 = Buffer.from('hello world!');
const buf2 = Buffer.allocUnsafe(5).fill('x');
buf1.copy(buf2,0,0,5);
console.log(buf2.toString());//hello

方法buf.slice([start[, end]])可以分割buffer,返回一個(gè)新的buffer,但是仍然是引用原buffer,因此改變?cè)璪uffer數(shù)據(jù),該新buffer也會(huì)跟著改變,如果參數(shù)start,end為負(fù)數(shù),則先要加上buffer的長(zhǎng)度再進(jìn)行計(jì)算,如下所示:

const buf1 = Buffer.from('hello world.');
const buf2 = buf1.slice(0);
console.log(buf2);//<Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64 2e>
buf2[0] = 88;
console.log(buf1);//<Buffer 58 65 6c 6c 6f 20 77 6f 72 6c 64 2e>
const buf3 = buf1.slice(-6,-1);
console.log(buf3.toString());//world

3、buffer讀寫(xiě)

buffer寫(xiě)操作通過(guò)write開(kāi)頭的寫(xiě)api來(lái)完成,主要有以下這些:

  • buf.write(string[, offset[, length]][, encoding]),向buffer寫(xiě)入字符串
  • buf.writeDoubleBE(value, offset[, noAssert])寫(xiě)入64位浮點(diǎn)型數(shù)字,大端對(duì)齊
  • buf.writeDoubleLE(value, offset[, noAssert]),寫(xiě)入64位浮點(diǎn)型數(shù)字,小端對(duì)齊
  • buf.writeFloatBE(value, offset[, noAssert]),寫(xiě)入32位浮點(diǎn)型數(shù)字,大端對(duì)齊
  • buf.writeFloatLE(value, offset[, noAssert]),寫(xiě)入32位浮點(diǎn)型數(shù)字,小端對(duì)齊
  • buf.writeInt8(value, offset[, noAssert]),寫(xiě)入有符號(hào)8位整型數(shù)字
  • buf.writeInt16BE(value, offset[, noAssert]),寫(xiě)入有符號(hào)16位整型數(shù)字,大端對(duì)齊
  • buf.writeInt16LE(value, offset[, noAssert]),寫(xiě)入有符號(hào)16位整型數(shù)字,小端對(duì)齊
  • buf.writeInt32BE(value, offset[, noAssert]),寫(xiě)入有符號(hào)32位整型數(shù)字,大端對(duì)齊
  • buf.writeInt32LE(value, offset[, noAssert]),寫(xiě)入有符號(hào)32位整型數(shù)字,小端對(duì)齊
  • buf.writeIntBE(value, offset, byteLength[, noAssert]),以下便不再累述
  • buf.writeIntLE(value, offset, byteLength[, noAssert])
  • buf.writeUInt8(value, offset[, noAssert])
  • buf.writeUInt16BE(value, offset[, noAssert])
  • buf.writeUInt16LE(value, offset[, noAssert])
  • buf.writeUInt32BE(value, offset[, noAssert])
  • buf.writeUInt32LE(value, offset[, noAssert])
  • buf.writeUIntBE(value, offset, byteLength[, noAssert])
  • buf.writeUIntLE(value, offset, byteLength[, noAssert])

buffer讀操作由read開(kāi)頭的api完成,主要有以下這些:

  • buf.readDoubleBE(offset[, noAssert])
  • buf.readDoubleLE(offset[, noAssert])
  • buf.readFloatBE(offset[, noAssert])
  • buf.readFloatLE(offset[, noAssert])
  • buf.readInt8(offset[, noAssert])
  • buf.readInt16BE(offset[, noAssert])
  • buf.readInt16LE(offset[, noAssert])
  • buf.readInt32BE(offset[, noAssert])
  • buf.readInt32LE(offset[, noAssert])
  • buf.readIntBE(offset, byteLength[, noAssert])
  • buf.readIntLE(offset, byteLength[, noAssert])
  • buf.readUInt8(offset[, noAssert])
  • buf.readUInt16BE(offset[, noAssert])
  • buf.readUInt16LE(offset[, noAssert])
  • buf.readUInt32BE(offset[, noAssert])
  • buf.readUInt32LE(offset[, noAssert])
  • buf.readUIntBE(offset, byteLength[, noAssert])
  • buf.readUIntLE(offset, byteLength[, noAssert])

使用如下所示,以32無(wú)符號(hào)整型為例:

const buf = Buffer.allocUnsafe(8);
buf.writeUInt32BE(0x12345678,0)
console.log(buf);
const data = buf.readUInt32BE(0);
console.log(data.toString(16));

最后利用buffer讀API完成一個(gè)獲取PNG格式圖片尺寸的小工具,在開(kāi)始編碼之前,先簡(jiǎn)單介紹下PNG文件組成,如下所示:

PNG文件標(biāo)志 PNG數(shù)據(jù)塊 …… PNG數(shù)據(jù)塊

這里我們只要用到PNG文件標(biāo)識(shí)和PNG數(shù)據(jù)塊的第一個(gè)塊IHDR文件頭數(shù)據(jù)塊。文件標(biāo)識(shí)是固定的8個(gè)字節(jié),為89 50 4E 47 0D 0A 1A 0A,IHDR數(shù)據(jù)塊的長(zhǎng)度為13個(gè)字節(jié),格式如下:

域的名稱(chēng) 字節(jié)數(shù) 說(shuō)明
Width 4 bytes 寬度
Height 4 bytes 高度
Bit depth 1 bytes 圖像深度
ColorType 1 bytes 顏色類(lèi)型
Compression method 1 bytes 壓縮方法
Filter method 1 bytes 濾波器方法
Interlace method 1 bytes 隔行掃描方法

開(kāi)始編碼,如下所示:

const fs = require('fs');
const path = require('path');

const argvs = process.argv.slice(2);
if(argvs.length<=0){
  console.error('請(qǐng)輸入圖片:png.js img1 img2 ...');
  process.exit(-1);
}
argvs.forEach((img,idx,arr)=>{
  var stat = fs.statSync(img);
  fs.open(img,'r',(err,fd)=>{
    if(err) throw err;
    var buff = Buffer.alloc(stat.size);
    fs.read(fd,buff,0,stat.size,0,(err, bytesRead, buffer)=>{
      if(err) throw err;
      fs.close(fd,()=>{});
      getImgDimension(buff,(err,dimension)=>{
        if(err) throw err;
        console.log(`${img}的尺寸為:${dimension.width}x${dimension.height}`);
      });
    });
  });
});
function getImgDimension(buff,cb){
  if((buff.toString('utf8',1,8) === 'PNG\r\n\x1a\n') && (buff.toString('utf8',12,16) === 'IHDR')){
    return cb(null,{
      width:buff.readUInt32BE(16),
      height:buff.readUInt32BE(20)
    }),!0;
  }else{
    return cb(new Error('不是PNG圖片'),{}),!1;
  }
}

執(zhí)行結(jié)果如下:

E:\developmentdocument\nodejsdemo>node png.js 20160824083157.png 下載.png
 20160824083157.png的尺寸為:195x195
下載.png的尺寸為:720x600

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • node使用Koa2搭建web項(xiàng)目的方法

    node使用Koa2搭建web項(xiàng)目的方法

    本篇文章主要介紹了node使用Koa2搭建web項(xiàng)目的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • NodeJS連接MongoDB數(shù)據(jù)庫(kù)時(shí)報(bào)錯(cuò)的快速解決方法

    NodeJS連接MongoDB數(shù)據(jù)庫(kù)時(shí)報(bào)錯(cuò)的快速解決方法

    下面小編就為大家?guī)?lái)一篇NodeJS連接MongoDB數(shù)據(jù)庫(kù)時(shí)報(bào)錯(cuò)的快速解決方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考
    2016-05-05
  • Node.js讀寫(xiě)文件之批量替換圖片的實(shí)現(xiàn)方法

    Node.js讀寫(xiě)文件之批量替換圖片的實(shí)現(xiàn)方法

    下面小編就為大家?guī)?lái)一篇Node.js讀寫(xiě)文件之批量替換圖片的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-09-09
  • node koa2 ssr項(xiàng)目搭建的方法步驟

    node koa2 ssr項(xiàng)目搭建的方法步驟

    這篇文章主要介紹了node koa2 ssr項(xiàng)目搭建的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 快速解決brew安裝特定版本flow的問(wèn)題

    快速解決brew安裝特定版本flow的問(wèn)題

    今天小編就為大家分享一篇快速解決brew安裝特定版本flow的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05
  • Koa2微信公眾號(hào)開(kāi)發(fā)之消息管理

    Koa2微信公眾號(hào)開(kāi)發(fā)之消息管理

    這篇文章主要介紹了Koa2微信公眾號(hào)開(kāi)發(fā)之消息管理,這一節(jié)我們就來(lái)看看公眾號(hào)的消息管理。并實(shí)現(xiàn)一個(gè)自動(dòng)回復(fù)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • 比較node.js和Deno

    比較node.js和Deno

    這篇文章主要介紹了node.js和Deno的區(qū)別,對(duì)deno感興趣的同學(xué),可以參考下
    2021-04-04
  • node中koa中間件機(jī)制詳解

    node中koa中間件機(jī)制詳解

    本篇文章主要主要介紹了node中koa中間件機(jī)制詳解,詳細(xì)的介紹了koa和兼容問(wèn)題,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-08-08
  • Nuxt配合Node在實(shí)際生產(chǎn)中的應(yīng)用詳解

    Nuxt配合Node在實(shí)際生產(chǎn)中的應(yīng)用詳解

    這篇文章主要介紹了Nuxt配合Node在實(shí)際生產(chǎn)中的應(yīng)用詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • nodejs中的讀取文件fs與文件路徑path解析

    nodejs中的讀取文件fs與文件路徑path解析

    這篇文章主要介紹了nodejs中的讀取文件fs與文件路徑path解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08

最新評(píng)論