配色: 字号:
第八课 Buffer
2020-12-22 | 阅:  转:  |  分享 
  
Node.js开发教师:王晓玲QQ:4260924邮箱:4260924@qq.com主要内容Buffer的概念Buffer的构建Bu
ffer常用的几种方法Buffer的概念Buffer是Node特有(区别于浏览器JavaScript)的数据类型,主要用来处理二
进制数据。Buffer类是随Node内核一起发布的核心库。Buffer库为Node.js带来了一种存储原始数据的方法,
可以让Node.js处理二进制数据,每当需要在Node.js中处理I/O操作中移动的数据时,就有可能使用Buffer库
。原始数据存储在Buffer类的实例中。一个Buffer类似于一个整数数组,但它对应于V8堆内存之外的一块原始内存。J
avaScript语言自身只有字符串数据类型,没有二进制数据类型。Buffer类,该类用来创建一个专门存放二进制数据的缓存区。
一个Buffer类似于一个整数数组,但它对应于V8堆内存之外的一块原始内存。Buffer对象占用的内存空间是不计算在Nod
e.js进程内存空间限制上的,因此,我们也常常会使用Buffer来存储需要占用大量内存的数据。Buffer的构建1、使用Buffe
r类直接初始化一个Buffer对象,参数可以是二进制数据组成的数组。varbuffer=newBuffer([0x74,0
xc3,0xa9,0x73,0x74]);参数也可以采用字符串来得到一个Buffer,同样可以调用构造函数来实现,如:var
buffer=newBuffer(“HelloWorld!”);在v6.0之前创建Buffer对象直接使用newBuff
er()构造函数来创建对象实例,但是Buffer对内存的权限操作相比很大,可以直接捕获一些敏感信息,所以在v6.0以后,官方文档里
面建议使用Buffer.from()接口去创建Buffer对象。目前推荐的使用Buffer.from方法来初始化一个Buff
er对象,上面的代码可以该写为如下形式:varbuffer=Buffer.from([0x74,0xc3,0xa9,0x
73,0x74]);参数也可以采用字符串来得到一个Buffer,同样可以调用构造函数来实现,如:varbuffer=Buff
er.from(“HelloWorld!”);Buffer的构建Buffer提供了以下API来创建Buffer类:Bu
ffer.alloc(size[,fill[,encoding]]):返回一个指定大小的Buffer实例,如果没有设置
fill,则默认填满0Buffer.allocUnsafe(size):返回一个指定大小的Buffer实例,但是它不会被初
始化,所以它可能包含敏感的数据Buffer.allocUnsafeSlow(size)Buffer.from(array):返回
一个被array的值初始化的新的Buffer实例(传入的array的元素只能是数字,不然就会自动被0覆盖)Buff
er.from(arrayBuffer[,byteOffset[,length]]):返回一个新建的与给定的ArrayBu
ffer共享同一内存的Buffer。Buffer.from(buffer):复制传入的Buffer实例的数据,并返回一个
新的Buffer实例Buffer.from(string[,encoding]):返回一个被string的值初始化的新
的Buffer实例Buffer的构建1.通过new来构建Buffervarbuf=newBuffer(10);buf.
length===10;//truevarbuf=newBuffer([10,20,30,40,50]);
buf.length===5varbuf=newBuffer("www.runoob.com","utf-8");b
uf.length===13utf-8是默认的编码方式,此外它同样支持以下编码:"ascii","utf8","utf1
6le","ucs2","base64"和"hex"。Buffer的构建使用中文创建buffer?使用unicdeo编码
规则,编码为二进制。varbuf=newBuffer("好","utf8");buf.length//3buf.to
JSON()//{type:''Buffer'',data:[229,165,189]}Buffer的构建2.通
过from来构建Buffer例子一:Buffer.from(array)varbuf=Buffer.from([0x62,
0x75,0x66,0x66,0x65,0x72]);console.log(buf.toString());例子二:Bu
ffer.from(string[,encoding])arbuf=Buffer.from(''thisisatést
'');//默认采用utf8//输出:thisisatéstconsole.log(buf.toString());
//默认编码是utf8,所以正常打印//输出:thisisatC)stconsole.log(buf.toString
(''ascii''));//转成字符串时,编码不是utf8,所以乱码通过string创建buffer,跟将buffer转成字符
串时,记得编码保持一致,不然会出现乱码,如下所示。Buffer的构建2.通过from来构建Buffer例子三:Buffer.fro
m(buffer)varbuff=Buffer.from(''buffer'');varbuff2=Buffer.from
(buff);console.log(buff.toString());//输出:bufferconsole.log(buf
f2.toString());//输出:bufferbuff2[0]=0x61;console.log(buff.toS
tring());//输出:bufferconsole.log(buff2.toString());//输出:auff
erBuffer的构建3.通过alloc来构建Buffervarbuf1=Buffer.alloc(10);//长度为
10的buffer,初始值为0x0varbuf2=Buffer.alloc(10,1);//长度为10的buffer
,初始值为0x1varbuf3=Buffer.allocUnsafe(10);//长度为10的buffer,初始值不确定
Buffer的比较1.buf.equals(otherBuffer)判断两个buffer实例存储的数据是否相同,如果是,返回tru
e,否则返回false。//例子一:编码一样,内容相同varbuf1=Buffer.from(''A'');varbuf2
=Buffer.from(''A'');console.log(buf1.equals(buf2));//true//例
子二:编码一样,内容不同varbuf3=Buffer.from(''A'');varbuf4=Buffer.from(''B
'');console.log(buf3.equals(buf4));//false//例子三:编码不一样,内容相同va
rbuf5=Buffer.from(''ABC'');//varbuf6=Buff
er.from(''414243'',''hex'');console.log(buf5.equals(buf6));Buffer的比较
2.buf.compare(target[,targetStart[,targetEnd[,sourceStart[,so
urceEnd]]]])同样是对两个buffer实例进行比较,不同的是:1.指定特定比较的范围(通过start、end指定)2.
返回值为整数,达标buf、target的大小关系返回值为:0:buf、target大小相同。1:buf大于target,也就是说
buf应该排在target之后。-1:buf小于target,也就是说buf应该排在target之前。Buffer的比较const
buf1=Buffer.from(''ABC'');constbuf2=Buffer.from(''BCD'');const
buf3=Buffer.from(''ABCD'');console.log(buf1.compare(buf1));//Pr
ints:0console.log(buf1.compare(buf2));//Prints:-1console.log(b
uf1.compare(buf3));//Prints:-1console.log(buf2.compare(buf1));
//Prints:1console.log(buf2.compare(buf3));//Prints:1//Print
s:[,,]
//(Thisresultisequalto:[buf1,buf3,buf2])console.log([buf1
,buf2,buf3].sort(Buffer.compare));Buffer的比较Buffer.compare(buf1,
buf2)跟buf.compare(target)大同小异,一般用于排序constbuf1=Buffer.from(''
1234'');constbuf2=Buffer.from(''0123'');constarr=[buf1,buf2];
//Prints:[,]//(This
resultisequalto:[buf2,buf1])console.log(arr.sort(Buffer.com
pare));Buffer的API接口Buffer对象转换成字符串如果想把一个Buffer对象转成字符串的形式,需要使用toStr
ing方法,调用格式为:buffer.toString([encoding],[start],[end])encoding—目标编
码格式start—开始位置end—结束位置Buffer支持的字符编码包括:ascii-仅支持7位ASCII数据。如果设
置去掉高位的话,这种编码是非常快的。utf8-多字节编码的Unicode字符。许多网页和其他文档格式都使用UTF-8。
utf16le-2或4个字节,小字节序编码的Unicode字符。支持代理对(U+10000至U+10FFFF)。
ucs2-utf16le的别名。base64-Base64编码。latin1-一种把Buffer编码成一字节编
码的字符串的方式。binary-latin1的别名。hex-将每个字节编码为两个十六进制字符Buffer还提供了isEn
coding方法来判断是否支持转换为目标编码格式Buffer的API接口Buffer对象转换成字符串把buf解码成字符串,用法比
较直观,看例子varbuff=Buffer.from(''hello'');console.log(buff.toString
());//helloconsole.log(buff.toString(''utf8'',0,2));//he
Buffer的API接口写缓冲区:Buffer.write(string[,offset[,length]][,encod
ing])将sring写入buffer实例,同时返回写入的字节数string-写入的字符串。offset-从buffer的
第几位开始写入,默认是0。length-写入多少个字节,默认是buf.length-offsetencoding-
使用的编码。默认为''utf8''。例子:buf=Buffer.alloc(256);len=buf.write("www
.runoob.com");console.log("写入字节数:"+len);Buffer的API接口合并BufferB
uffer.concat(list[,totalLength])list-用于合并的Buffer对象数组列表。total
Length-指定合并后Buffer对象的总长度。例子:varbuff1=Buffer.alloc(10);varbu
ff2=Buffer.alloc(20);vartotalLength=buff1.length+buff2.len
gth;console.log(totalLength);//30varbuff3=Buffer.concat([bu
ff1,buff2],totalLength);console.log(buff3.length);//30Buffer
的API接口totalLength还有两点需要注意。假设list里面所有buffer的长度累加和为lengthtotalLengt
h>length:返回长度为totalLength的Buffer实例,超出长度的部分填充0。totalLengthgth:返回长度为totalLength的Buffer实例,后面部分舍弃。varbuff4=Buffer.from([1,
2]);varbuff5=Buffer.from([3,4]);varbuff6=Buffer.concat([bu
ff4,buff5],5);console.log(buff6.length);//console.log(buff6)
;//varbuff7=Buffer.concat([buff4,bu
ff5],3);console.log(buff7.length);//3console.log(buff7);//
Buffer的API接口拷贝:Buffer.copy(targetBuffer[,targe
tStart[,sourceStart[,sourceEnd]]])buffer的数据拷贝到targetBuffer里去tar
getBuffer-要拷贝的Buffer对象。targetStart-数字,可选,默认:0sourceStart
-数字,可选,默认:0sourceEnd-数字,可选,默认:buffer.length例子:varbuff1
=Buffer.from([1,2]);varbuff2=Buffer.alloc(2);buff1.copy(buf
f2);console.log(buff2);//Buffer的API接口另外三个参数比较直观
constbuf1=Buffer.alloc(26);constbuf2=Buffer.alloc(26,''!'');f
or(leti=0;i<26;i++){buf1[i]=i+97;//97isthede
cimalASCIIvaluefor''a''}buf1.copy(buf2,8,16,20);console.log(
buf2.toString(''ascii'',0,25));//Prints:!!!!!!!!qrst!!!!!!!!!!!
!!Buffer的API接口转成JSON字符串:Buffer.toJSON()varbuff=Buffer.from(''
hello'');console.log(buff.toJSON());//{type:''Buffer'',data:
[104,101,108,108,111]}将JS对象转为字符串:JSON.stringify(obj)。var
json={aa:[''sdddssd''],bb:[''892394829342'',''238947239847''],
cc:[''11111111111111'']}varstring=JSON.stringify(json)consol
e.log(string);Buffer的API接口将字符串转为JS对象:JSON.parse(string)console.l
og(JSON.parse(string));{aa:[''sdddssd''],bb:[''892394829342'',''
238947239847''],cc:[''11111111111111'']}Buffer的API接口填充:buf.fill(
value[,offset[,end]][,encoding])用value填充buf,常用于初始化buf。参数说明如下:v
alue:用来填充的内容,可以是Buffer、String或Integer。offset:从第几位开始填充,默认是0。end:停止
填充的位置,默认是buf.length。encoding:如果value是String,那么为value的编码,默认是utf8v
arbuff=Buffer.alloc(20).fill(''a'');console.log(buff.toString())
;//aaaaaaaaaaaaaaaaaaaaBuffer的API接口遍历:buf.values()、buf.keys()、
buf.entries()用于对buf进行for...of遍历,例子:varbuff=Buffer.from(''abcde''
);for(constkeyofbuff.keys()){console.log(''keyis%d'',key);}f
or(constvalueofbuff.values()){console.log(''valueis%d'',valu
e);}for(constpairofbuff.entries()){console.log(''buff[%d]===
%d'',pair[0],pair[1]);}Buffer的API接口截取:buf.slice([start[,end]])用
于截取buf,并返回一个新的Buffer实例。varbuff1=Buffer.from(''abcde'');console.l
og(buff1);//varbuff2=buff1.slice();c
onsole.log(buff2);//varbuff3=buff1.s
lice(1,3);console.log(buff3);//buff3[0]=97;
//parseInt(61,16)==>97console.log(buff1);//
要注意的是,这里返回的Buffer实例,指向的仍然是buf的内存地址,所以对新Buffer实例的修改,也会影响到buf。Buffe
r其它常用的方法1buf.length返回这个buffer的bytes数。注意这未必是buffer里面内容的大小。
length是buffer对象所分配的内存数,它不会随着这个buffer对象内容的改变而改变。2buf[index]获取
或设置指定的字节。返回值代表一个字节,所以返回值的合法范围是十六进制0x00到0xFF或者十进制0至255。3buf.fill
(value[,offset][,end])使用指定的value来填充这个buffer。如果没有指定offset(默
认是0)并且end(默认是buffer.length),将会填充整个buffer。Node.js本章作业1、创建一个
缓冲区并添加字符串“thisisnode.jsbook”。在缓冲区增加字符串“我要认真学习Node.js”,然后获取缓冲
区的长度,并输出到控制台。;2、预习FileSystem相关内容谢谢!Node有自身的事件循环机制,从I/O观察中取得是否还
有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调
等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数
。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件
,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/
O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可
以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,
调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕
后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Nod
e是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/
O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求
对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱
动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这
时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态
,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I
/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请
求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循
环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node
有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请
求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理
完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循
环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提
交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信
息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/
O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态
、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观
察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是
否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的
回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调
函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的
事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在
I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流
程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事
件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行
完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,N
ode是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的
I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改
请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件
为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行
,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行
状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异
步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一
个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事
件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的No
de有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这
个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将
处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事
件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录
了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/
O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从
I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的
状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/
O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取
得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事
件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行
回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执
行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息
,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上
述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果
有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的Node有自身的事件循环机制,从I/O观察中取得是否还有待执行的事件,如果有事件,调用对应的I/O线程执行,这时会生产一个请求对象,这个请求对象记录了提交I/O的状态、记录了事件的回调等信息,在I/O线程执行完毕后,会修改请求对象的执行状态,并通知事件循环系统,将处理完成的I/O信息通知I/O观察者,执行回调函数。从上述流程可以看出,Node是以事件为驱动来实现异步I/O的
献花(0)
+1
(本文系中转站199首藏)