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的 |
|